79 std::atomic<Int_t> TStreamerInfo::fgCount{0};
81 const Int_t kMaxLen = 1024;
83 ClassImp(TStreamerInfo);
85 static void R__TObjArray_InsertAt(TObjArray *arr, TObject *obj, Int_t at)
88 Int_t last = arr->GetLast();
89 arr->AddAtAndExpand(arr->At(last),last+1);
90 for(Int_t ind = last-1; ind >= at; --ind) {
91 arr->AddAt( arr->At(ind), ind+1);
96 static void R__TObjArray_InsertAt(TObjArray *arr, std::vector<TStreamerArtificial*> &objs, Int_t at)
99 Int_t offset = objs.size();
100 Int_t last = arr->GetLast();
101 arr->AddAtAndExpand(arr->At(last),last+offset);
102 for(Int_t ind = last-1; ind >= at; --ind) {
103 arr->AddAt( arr->At(ind), ind+offset);
105 for(
size_t ins = 0; ins < objs.size(); ++ins) {
106 arr->AddAt(objs[ins], at+ins);
110 static void R__TObjArray_InsertAfter(TObjArray *arr, TObject *newobj, TObject *oldobj)
113 Int_t last = arr->GetLast();
115 while (at<last && arr->At(at) != oldobj) {
119 R__TObjArray_InsertAt(arr, newobj, at);
122 static void R__TObjArray_InsertBefore(TObjArray *arr, TObject *newobj, TObject *oldobj)
125 Int_t last = arr->GetLast();
127 while (at<last && arr->At(at) != oldobj) {
130 R__TObjArray_InsertAt(arr, newobj, at);
133 enum class EUniquePtrOffset : char
143 TStreamerInfo::TStreamerInfo()
157 fOnFileClassVersion = 0;
158 fOldVersion = Class()->GetClassVersion();
159 fNVirtualInfoLoc = 0;
165 fReadMemberWiseVecPtr = 0;
167 fWriteObjectWise = 0;
168 fWriteMemberWise = 0;
169 fWriteMemberWiseVecPtr = 0;
176 TStreamerInfo::TStreamerInfo(TClass *cl)
177 : TVirtualStreamerInfo(cl)
182 fElements =
new TObjArray();
191 fClassVersion = fClass->GetClassVersion();
192 fOnFileClassVersion = 0;
193 fOldVersion = Class()->GetClassVersion();
194 fNVirtualInfoLoc = 0;
200 fReadMemberWiseVecPtr = 0;
202 fWriteObjectWise = 0;
203 fWriteMemberWise = 0;
204 fWriteMemberWiseVecPtr = 0;
211 TStreamerInfo::~TStreamerInfo()
213 delete [] fComp; fComp = 0;
214 delete [] fCompFull; fCompFull = 0;
215 delete [] fCompOpt; fCompOpt = 0;
216 delete [] fVirtualInfoLoc; fVirtualInfoLoc =0;
218 delete fReadObjectWise;
219 delete fReadMemberWise;
220 delete fReadMemberWiseVecPtr;
222 delete fWriteObjectWise;
223 delete fWriteMemberWise;
224 delete fWriteMemberWiseVecPtr;
227 if (!fElements)
return;
229 delete fElements; fElements=0;
237 struct TPreventRecursiveBuildGuard {
238 TPreventRecursiveBuildGuard(TStreamerInfo* info): fInfo(info) {
239 fInfo->SetBit(TStreamerInfo::kBuildRunning);
240 fInfo->SetBit(TStreamerInfo::kBuildOldUsed);
242 ~TPreventRecursiveBuildGuard() {
243 fInfo->ResetBit(TStreamerInfo::kBuildOldUsed);
244 fInfo->ResetBit(TStreamerInfo::kBuildRunning);
246 TStreamerInfo* fInfo;
256 void TStreamerInfo::Build()
259 if (fIsCompiled)
return;
261 R__LOCKGUARD(gInterpreterMutex);
264 if (fIsCompiled)
return;
267 if (fIsBuilt)
return;
270 if (TestBit(TStreamerInfo::kBuildRunning))
return;
273 TPreventRecursiveBuildGuard buildGuard(
this);
275 if (fClass->GetCollectionProxy()) {
276 TVirtualCollectionProxy *proxy = fClass->GetCollectionProxy();
278 if (proxy->GetValueClass()) {
279 title.Form(
"<%s%s> Used to call the proper TStreamerInfo case",proxy->GetValueClass()->GetName(),proxy->HasPointers() ?
"*" :
"");
281 title .Form(
"<%s%s> Used to call the proper TStreamerInfo case",TDataType::GetTypeName(proxy->GetType()),proxy->HasPointers() ?
"*" :
"");
283 TStreamerElement* element =
new TStreamerSTL(
"This", title.Data(), 0, fClass->GetName(), *proxy, 0);
284 fElements->Add(element);
286 fCheckSum = fClass->GetCheckSum();
291 TStreamerElement::Class()->IgnoreTObjectStreamer();
293 fClass->BuildRealData();
295 fCheckSum = fClass->GetCheckSum();
297 Bool_t needAllocClass = kFALSE;
298 Bool_t wasCompiled = fComp != 0;
299 ROOT::TSchemaRuleSet::TMatches rules;
300 if (fClass->GetSchemaRules()) {
301 rules = fClass->GetSchemaRules()->FindRules(fClass->GetName(), fClassVersion);
312 if (strncmp(fClass->GetName(),
"pair<", 5)) {
313 const bool isCollection = fClass->GetCollectionProxy();
314 const bool isString = !strcmp(fClass->GetName(),
"string");
315 TBaseClass* base = 0;
316 TIter nextb(fClass->GetListOfBases());
317 while ((base = (TBaseClass*)nextb())) {
318 TStreamerElement* element = 0;
319 Int_t offset = base->GetDelta();
320 if (offset == kMissing) {
323 if (offset == kNeedObjectForVirtualBaseClass) {
324 Error(
"Build()",
"Cannot stream virtual base %s of class %s",
325 base->GetName(), fClass->GetName());
328 const char* bname = base->GetName();
329 const char* btitle = base->GetTitle();
331 if (!strcmp(bname,
"string")) {
332 element =
new TStreamerSTLstring(bname, btitle, offset, bname, kFALSE);
333 }
else if (base->IsSTLContainer()) {
334 TVirtualCollectionProxy *proxy = base->GetClassPointer()->GetCollectionProxy();
335 if (proxy) element =
new TStreamerSTL(bname, btitle, offset, bname, *proxy, kFALSE);
336 else element =
new TStreamerSTL(bname, btitle, offset, bname, 0, kFALSE);
337 if (fClass->IsLoaded() && ((TStreamerSTL*)element)->GetSTLtype() != ROOT::kSTLvector) {
338 if (!element->GetClassPointer()->IsLoaded()) {
339 Error(
"Build",
"The class \"%s\" is compiled and its base class \"%s\" is a collection and we do not have a dictionary for it, we will not be able to read or write this base class.",GetName(),bname);
345 element =
new TStreamerBase(bname, btitle, offset);
346 TClass* clm = element->GetClassPointer();
352 clm =
new TClass(bname,1,TClass::kForwardDeclared,
true );
353 Warning(
"Build",
"%s: base class %s has no streamer or dictionary it will not be saved", GetName(), clm->GetName());
358 if ((clm == TObject::Class()) && fClass->CanIgnoreTObjectStreamer()) {
363 SetBit(kIgnoreTObjectStreamer);
367 element->SetType(-1);
369 if (!clm->IsLoaded() && !(isCollection || isString)) {
372 Warning(
"Build",
"%s: base class %s has no streamer or dictionary it will not be saved", GetName(), clm->GetName());
377 fElements->Add(element);
388 std::string typeNameBuf;
389 std::string trueTypeNameBuf;
390 TIter nextd(fClass->GetListOfDataMembers());
391 while ((dm = (TDataMember*) nextd())) {
392 if (fClass->GetClassVersion() == 0) {
395 if (!dm->IsPersistent()) {
398 TMemberStreamer* streamer = 0;
399 Int_t offset = GetDataMemberOffset(dm, streamer);
400 if (offset == kMissing) {
403 TStreamerElement* element = 0;
407 const char* dmName = dm->GetName();
408 const char* dmTitle = dm->GetTitle();
409 const char* dmType = dm->GetTypeName();
410 const char* dmFull = dm->GetTrueTypeName();
411 Bool_t dmIsPtr = dm->IsaPointer();
412 TDataType* dt(
nullptr);
413 Int_t ndim = dm->GetArrayDim();
414 std::array<Int_t, 5> maxIndices;
415 Bool_t isStdArray(kFALSE);
419 trueTypeNameBuf = typeNameBuf = TClassEdit::GetNameForIO(dmFull, TClassEdit::EModType::kNone, &nameChanged);
421 if (TClassEdit::IsUniquePtr(dmFull)) {
424 while(typeNameBuf.back() ==
'*') typeNameBuf.pop_back();
425 dmFull = trueTypeNameBuf.c_str();
426 dmType = typeNameBuf.c_str();
428 if ((isStdArray = TClassEdit::IsStdArray(dmType))){
429 TClassEdit::GetStdArrayProperties(dmType,
433 trueTypeNameBuf = typeNameBuf;
434 while(typeNameBuf.back() ==
'*') typeNameBuf.pop_back();
435 dmFull = dmType = typeNameBuf.c_str();
436 dt = gROOT->GetType(dmType);
439 TDataMember* dmCounter = 0;
448 const char* lbracket = TVirtualStreamerInfo::GetElementCounterStart(dmTitle);
449 const char* rbracket = ::strchr(dmTitle,
']');
450 if (lbracket && rbracket) {
451 const char* counterName = dm->GetArrayIndex();
452 TRealData* rdCounter = (TRealData*) fClass->GetListOfRealData()->FindObject(counterName);
453 if (!rdCounter || rdCounter->TestBit(TRealData::kTransient)) {
454 Error(
"Build",
"%s, discarding: %s %s, illegal %s\n", GetName(), dmFull, dmName, dmTitle);
457 dmCounter = rdCounter->GetDataMember();
458 TDataType* dtCounter = dmCounter->GetDataType();
459 Bool_t isInteger = dtCounter && ((dtCounter->GetType() == 3) || (dtCounter->GetType() == 13));
460 if (!dtCounter || !isInteger) {
461 Error(
"Build",
"%s, discarding: %s %s, illegal [%s] (must be Int_t)\n", GetName(), dmFull, dmName, counterName);
464 TStreamerBasicType* bt = TStreamerInfo::GetElementCounter(counterName, dmCounter->GetClass());
466 if (dmCounter->GetClass()->Property() & kIsAbstract) {
469 Error(
"Build",
"%s, discarding: %s %s, illegal [%s] must be placed before \n", GetName(), dmFull, dmName, counterName);
474 if (!dt && !isStdArray) dt = dm->GetDataType();
477 Int_t dtype = dt->GetType();
479 if (!dmCounter && (strstr(dmFull,
"char*") || strstr(dmFull,
"Char_t*"))) {
481 dsize =
sizeof(
char*);
483 if (dtype == kOther_t || dtype == kNoType_t) {
484 Error(
"Build",
"%s, unknown type: %s %s", GetName(), dmFull, dmName);
486 }
else if (dmIsPtr && (dtype != kCharStar)) {
489 element =
new TStreamerBasicPointer(dmName, dmTitle, offset, dtype, dm->GetArrayIndex(), dmCounter->GetClass()->GetName(), dmCounter->GetClass()->GetClassVersion(), dmFull);
491 if ((fName ==
"TString") || (fName ==
"TClass")) {
494 Error(
"Build",
"%s, discarding: %s %s, no [dimension]\n", GetName(), dmFull, dmName);
499 if ((fClass == TObject::Class()) && !strcmp(dmName,
"fBits")) {
504 element =
new TStreamerBasicType(dmName, dmTitle, offset, dtype, dmFull);
508 static const char* full_string_name =
"basic_string<char,char_traits<char>,allocator<char> >";
509 if (!strcmp(dmType,
"string") || !strcmp(dmType,
"std::string") || !strcmp(dmType, full_string_name)) {
510 element =
new TStreamerSTLstring(dmName, dmTitle, offset, dmFull, dmIsPtr);
511 }
else if (dm->IsSTLContainer()) {
512 TVirtualCollectionProxy *proxy = TClass::GetClass(dmType )->GetCollectionProxy();
513 if (proxy) element =
new TStreamerSTL(dmName, dmTitle, offset, dmFull, *proxy, dmIsPtr);
514 else element =
new TStreamerSTL(dmName, dmTitle, offset, dmFull, dmFull, dmIsPtr);
515 bool hasCustomAlloc = proxy ? proxy->GetProperties() & TVirtualCollectionProxy::kCustomAlloc : kFALSE;
516 if (((TStreamerSTL*)element)->GetSTLtype() != ROOT::kSTLvector || hasCustomAlloc) {
517 auto printErrorMsg = [&](
const char* category)
519 Error(
"Build",
"The class \"%s\" is %s and for its data member \"%s\" we do not have a dictionary for the collection \"%s\". Because of this, we will not be able to read or write this data member.",GetName(), category, dmName, dmType);
521 if (fClass->IsLoaded()) {
522 if (!element->GetClassPointer()->IsLoaded()) {
523 printErrorMsg(
"compiled");
527 }
else if (fClass->GetState() == TClass::kInterpreted) {
528 if (element->GetClassPointer()->GetCollectionProxy()->GetProperties() & TVirtualCollectionProxy::kIsEmulated) {
529 printErrorMsg(
"interpreted");
536 TClass* clm = TClass::GetClass(dmType);
538 Error(
"Build",
"%s, unknown type: %s %s\n", GetName(), dmFull, dmName);
549 element =
new TStreamerLoop(dmName, dmTitle, offset, dm->GetArrayIndex(), dmCounter->GetClass()->GetName(), dmCounter->GetClass()->GetClassVersion(), dmFull);
551 if (clm->IsTObject()) {
552 element =
new TStreamerObjectPointer(dmName, dmTitle, offset, dmFull);
554 element =
new TStreamerObjectAnyPointer(dmName, dmTitle, offset, dmFull);
555 if (!streamer && !clm->GetStreamer() && !clm->IsLoaded()) {
556 Error(
"Build",
"%s: %s has no streamer or dictionary, data member %s will not be saved", GetName(), dmFull, dmName);
560 }
else if (clm->IsTObject()) {
561 element =
new TStreamerObject(dmName, dmTitle, offset, dmFull);
562 }
else if ((clm == TString::Class()) && !dmIsPtr) {
563 element =
new TStreamerString(dmName, dmTitle, offset);
565 element =
new TStreamerObjectAny(dmName, dmTitle, offset, dmFull);
566 if (!streamer && !clm->GetStreamer() && !clm->IsLoaded()) {
567 Warning(
"Build",
"%s: %s has no streamer or dictionary, data member \"%s\" will not be saved", GetName(), dmFull, dmName);
577 dsize = dm->GetUnitSize();
579 for (Int_t i = 0; i < ndim; ++i) {
581 if (isStdArray) maxIndex = maxIndices[i];
582 else maxIndex = dm->GetMaxIndex(i);
583 element->SetMaxIndex(i, maxIndex);
585 element->SetArrayDim(ndim);
587 Int_t narr = element->GetArrayLength();
591 element->SetSize(dsize*narr);
592 element->SetStreamer(streamer);
594 Int_t k = element->GetType();
595 if (k == kStreamer) {
597 element->SetType(-1);
601 if ( !wasCompiled && (rules && rules.HasRuleWithSource( element->GetName(), kTRUE )) ) {
602 needAllocClass = kTRUE;
608 TStreamerElement *cached = element;
610 if (element->GetNewType()>0
611 && rules && !rules.HasRuleWithTarget( element->GetName(), kTRUE ) )
613 TStreamerElement *copy = (TStreamerElement*)element->Clone();
614 fElements->Add(copy);
615 copy->SetBit(TStreamerElement::kRepeat);
622 TStreamerElement *writecopy = (TStreamerElement*)element->Clone();
623 fElements->Add(element);
624 writecopy->SetBit(TStreamerElement::kWrite);
625 writecopy->SetNewType( writecopy->GetType() );
626 writecopy->SetOffset( element->GetOffset() );
630 cached->SetBit(TStreamerElement::kCache);
631 cached->SetNewType( cached->GetType() );
634 fElements->Add(element);
638 InsertArtificialElements(rules);
640 if (needAllocClass) {
641 TStreamerInfo *infoalloc = (TStreamerInfo *)Clone(TString::Format(
"%s@@%d",GetName(),GetClassVersion()));
643 Error(
"Build",
"Could you create a TStreamerInfo for %s\n",TString::Format(
"%s@@%d",GetName(),GetClassVersion()).Data());
646 infoalloc->SetBit(kBuildOldUsed,
false);
650 infoalloc->BuildCheck();
651 infoalloc->BuildOld();
653 TClass *allocClass = infoalloc->GetClass();
656 TIter next(fElements);
657 TStreamerElement* element;
658 while ((element = (TStreamerElement*) next())) {
659 if (element->TestBit(TStreamerElement::kRepeat) && element->IsaPointer()) {
660 TStreamerElement *other = (TStreamerElement*) infoalloc->GetElements()->FindObject(element->GetName());
662 other->SetBit(TStreamerElement::kDoNotDelete);
666 infoalloc->GetElements()->Compress();
669 TIter next(fElements);
670 TStreamerElement* element;
671 while ((element = (TStreamerElement*) next())) {
672 if (element->TestBit(TStreamerElement::kCache)) {
673 element->SetOffset(infoalloc->GetOffset(element->GetName()));
678 TStreamerElement *el =
new TStreamerArtificial(
"@@alloc",
"", 0, TStreamerInfo::kCacheNew, allocClass->GetName());
679 R__TObjArray_InsertAt( fElements, el, 0 );
681 el =
new TStreamerArtificial(
"@@dealloc",
"", 0, TStreamerInfo::kCacheDelete, allocClass->GetName());
682 fElements->Add( el );
697 void TStreamerInfo::BuildCheck(TFile *file )
699 R__LOCKGUARD(gInterpreterMutex);
701 fClass = TClass::GetClass(GetName());
707 fClass =
new TClass(GetName(), (Version_t)fClassVersion);
708 fClass->SetBit(TClass::kIsEmulation);
712 if (GetElements()->GetEntries() == 1) {
713 TObject *element = GetElements()->UncheckedAt(0);
714 Bool_t isstl = element && strcmp(
"This",element->GetName())==0;
716 if (element->GetTitle()[0] ==
'<') {
718 TString content = element->GetTitle();
720 for(Int_t c = 1; c < content.Length(); ++c) {
721 if (content[c] ==
'<') ++level;
722 else if (content[c] ==
'>') --level;
728 content.Prepend(
"vector");
729 TClass *clequiv = TClass::GetClass(content);
730 TVirtualCollectionProxy *proxy = clequiv->GetCollectionProxy();
733 "Update the collection proxy of the class \"%s\" \n"
734 "\tto be similar to \"%s\".",
735 GetName(),content.Data());
736 fClass->CopyCollectionProxy( *proxy );
738 Warning(
"BuildCheck",
"\n\
739 The class %s had a collection proxy when written but it is not an STL\n \
740 collection and we did not record the type of the content of the collection.\n \
741 We will claim the content is a bool (i.e. no data will be read).",
748 if (fClass->GetCollectionType() > ROOT::kNotSTL) {
749 if (TClassEdit::IsSTLCont(fClass->GetName())) {
757 if (0 == strcmp(
"string",fClass->GetName())) {
763 const TObjArray *array = fClass->GetStreamerInfos();
764 TStreamerInfo* info = 0;
766 if (fClass->TestBit(TClass::kIsEmulation) && array->GetEntries()==0) {
772 ::Warning(
"TClass::TClass",
"no dictionary for class %s is available", GetName());
777 if (GetElements()->GetEntries() == 1) {
778 TObject *element = GetElements()->UncheckedAt(0);
779 Bool_t isstl = element && strcmp(
"This",element->GetName())==0;
780 if (isstl && !fClass->GetCollectionProxy()) {
781 if (element->GetTitle()[0] ==
'<') {
783 TString content = element->GetTitle();
785 for(Int_t c = 1; c < content.Length(); ++c) {
786 if (content[c] ==
'<') ++level;
787 else if (content[c] ==
'>') --level;
793 content.Prepend(
"vector");
794 TClass *clequiv = TClass::GetClass(content);
795 TVirtualCollectionProxy *proxy = clequiv->GetCollectionProxy();
798 "Update the collection proxy of the class \"%s\" \n"
799 "\tto be similar to \"%s\".",
800 GetName(),content.Data());
801 fClass->CopyCollectionProxy( *proxy );
803 Warning(
"BuildCheck",
"\n\
804 The class %s had a collection proxy when written but it is not an STL\n \
805 collection and we did not record the type of the content of the collection.\n \
806 We will claim the content is a bool (i.e. no data will be read).",
820 Bool_t searchOnChecksum = kFALSE;
821 if (fClass->IsLoaded() && fClass->GetClassVersion() >= 2) {
824 if (fOnFileClassVersion >= 2) {
828 searchOnChecksum = kFALSE;
834 searchOnChecksum = kTRUE;
836 }
else if (fClass->IsLoaded() && !fClass->IsForeign()) {
841 searchOnChecksum = kFALSE;
843 }
else if (fClass->IsLoaded() ) {
847 searchOnChecksum = kTRUE;
853 if (fOnFileClassVersion >= 2) {
857 searchOnChecksum = kFALSE;
863 searchOnChecksum = kTRUE;
865 TStreamerInfo* v1 = (TStreamerInfo*) array->At(1);
867 if (fCheckSum != v1->GetCheckSum()) {
868 fClassVersion = array->GetLast() + 1;
874 if (!searchOnChecksum) {
875 if (fClassVersion < (array->GetEntriesFast() - 1)) {
876 info = (TStreamerInfo*) array->At(fClassVersion);
879 Int_t ninfos = array->GetEntriesFast() - 1;
880 for (Int_t i = -1; i < ninfos; ++i) {
881 info = (TStreamerInfo*) array->UncheckedAt(i);
885 if (fCheckSum == info->GetCheckSum() && (info->GetOnFileClassVersion()==1 || info->GetOnFileClassVersion()==0)) {
895 ninfos = array->GetEntriesFast() - 1;
897 while ((slot < ninfos) && (array->UncheckedAt(slot) != 0)) {
900 fClassVersion = slot;
911 Bool_t match = kTRUE;
912 Bool_t done = kFALSE;
913 Bool_t oldIsNonVersioned = kFALSE;
914 if (fClassVersion!=0 && !fClass->TestBit(TClass::kWarned) && (fClassVersion == info->GetClassVersion()) && (fCheckSum != info->GetCheckSum())) {
918 oldIsNonVersioned = info->fOnFileClassVersion==1 && info->fClassVersion != 1;
920 if (fClass->IsLoaded() && (fClassVersion == fClass->GetClassVersion()) && fClass->HasDataMemberInfo()) {
929 if ( (fCheckSum == fClass->GetCheckSum() || fClass->MatchLegacyCheckSum(fCheckSum) )
930 &&(info->GetCheckSum() == fClass->GetCheckSum() || fClass->MatchLegacyCheckSum(info->GetCheckSum()))
935 if (fOldVersion <= 2) {
940 if (!match && CompareContent(0,info,kFALSE,kFALSE,file)) {
943 #ifdef TEST_FOR_BACKWARD_COMPATIBILITY_ABSTRACT_CLASSES
944 if (!match && file->GetVersion() < 51800 && fClass && (fClass->Property() & kIsAbstract)
945 && fClass->GetListOfDataMembers()->GetEntries() != 0)
969 oldIsNonVersioned = info->fOnFileClassVersion==1 && info->fClassVersion != 1;
979 if (fCheckSum == info->GetCheckSum(TClass::kCurrentCheckSum)
980 || info->MatchLegacyCheckSum(fCheckSum)
981 || GetCheckSum(TClass::kCurrentCheckSum) == info->fCheckSum
982 || MatchLegacyCheckSum(info->GetCheckSum())
983 || GetCheckSum(TClass::kCurrentCheckSum) == info->GetCheckSum(TClass::kCurrentCheckSum))
987 if (fOldVersion <= 2) {
992 if (!match && CompareContent(0,info,kFALSE,kFALSE,file)) {
997 if (info->IsBuilt()) {
999 fNumber = info->GetNumber();
1000 Int_t nel = fElements->GetEntriesFast();
1001 TObjArray* elems = info->GetElements();
1002 TStreamerElement* e1 = 0;
1003 TStreamerElement* e2 = 0;
1004 for (Int_t i = 0; i < nel; ++i) {
1005 e1 = (TStreamerElement*) fElements->UncheckedAt(i);
1006 e2 = (TStreamerElement*) elems->At(i);
1010 if (strlen(e1->GetTitle()) != strlen(e2->GetTitle())) {
1011 e2->SetTitle(e1->GetTitle());
1017 fClass->RemoveStreamerInfo(fClassVersion);
1021 if (!match && !fClass->TestBit(TClass::kWarned)) {
1022 if (oldIsNonVersioned) {
1024 Warning(
"BuildCheck",
"\n\
1025 The class %s transitioned from not having a specified class version\n\
1026 to having a specified class version (the current class version is %d).\n\
1027 However too many different non-versioned layouts of the class have been\n\
1028 loaded so far. This prevent the proper reading of objects written with\n\
1029 the class layout version %d, in particular from the file:\n\
1031 To work around this issue, load fewer 'old' files in the same ROOT session.",
1032 GetName(),fClass->GetClassVersion(),fClassVersion,file->GetName());
1034 Warning(
"BuildCheck",
"\n\
1035 The class %s transitioned from not having a specified class version\n\
1036 to having a specified class version (the current class version is %d).\n\
1037 However too many different non-versioned layouts of the class have been\n\
1038 loaded so far. This prevent the proper reading of objects written with\n\
1039 the class layout version %d.\n\
1040 To work around this issue, load fewer 'old' files in the same ROOT session.",
1041 GetName(),fClass->GetClassVersion(),fClassVersion);
1046 Warning(
"BuildCheck",
"\n\
1047 The StreamerInfo for version %d of class %s read from the file %s\n\
1048 has a different checksum than the previously loaded StreamerInfo.\n\
1049 Reading objects of type %s from the file %s \n\
1050 (and potentially other files) might not work correctly.\n\
1051 Most likely the version number of the class was not properly\n\
1052 updated [See ClassDef(%s,%d)].",
1053 fClassVersion, GetName(), file->GetName(), GetName(), file->GetName(), GetName(), fClassVersion);
1055 Warning(
"BuildCheck",
"\n\
1056 The StreamerInfo from %s does not match existing one (%s:%d)\n\
1057 The existing one has not been used yet and will be discarded.\n\
1058 Reading the file %s will work properly, however writing object of\n\
1059 type %s will not work properly. Most likely the version number\n\
1060 of the class was not properly updated [See ClassDef(%s,%d)].",
1061 file->GetName(), GetName(), fClassVersion,file->GetName(),GetName(), GetName(), fClassVersion);
1065 Warning(
"BuildCheck",
"\n\
1066 The StreamerInfo for version %d of class %s\n\
1067 has a different checksum than the previously loaded StreamerInfo.\n\
1068 Reading objects of type %s\n\
1069 (and potentially other files) might not work correctly.\n\
1070 Most likely the version number of the class was not properly\n\
1071 updated [See ClassDef(%s,%d)].",
1072 fClassVersion, GetName(), GetName(), GetName(), fClassVersion);
1074 Warning(
"BuildCheck",
"\n\
1075 The StreamerInfo from %s does not match existing one (%s:%d)\n\
1076 The existing one has not been used yet and will be discarded.\n\
1077 Reading should work properly, however writing object of\n\
1078 type %s will not work properly. Most likely the version number\n\
1079 of the class was not properly updated [See ClassDef(%s,%d)].",
1080 file->GetName(), GetName(), fClassVersion, GetName(), GetName(), fClassVersion);
1084 CompareContent(0,info,kTRUE,kTRUE,file);
1085 fClass->SetBit(TClass::kWarned);
1093 if (fClass->IsLoaded()
1094 && fClass->HasDataMemberInfo()
1095 && (fClassVersion != 0)
1096 && (fClassVersion == fClass->GetClassVersion())
1097 && (fCheckSum != fClass->GetCheckSum())) {
1105 if (!fClass->MatchLegacyCheckSum(fCheckSum)) {
1107 Bool_t warn = !fClass->TestBit(TClass::kWarned);
1109 warn = !CompareContent(fClass,0,kFALSE,kFALSE,file);
1111 #ifdef TEST_FOR_BACKWARD_COMPATIBILITY_ABSTRACT_CLASSES
1112 if (warn && file->GetVersion() < 51800 && fClass && (fClass->Property() & kIsAbstract)
1113 && fClass->GetListOfDataMembers()->GetEntries() != 0)
1132 #endif // TEST_FOR_BACKWARD_COMPATIBILITY
1133 if (warn && (fOldVersion <= 2)) {
1136 TIter nextBC(fClass->GetListOfBases());
1138 while ((bc = (TBaseClass*) nextBC())) {
1139 if (bc->GetClassPointer()->GetCollectionType()) {
1146 Warning(
"BuildCheck",
"\n\
1147 The StreamerInfo of class %s read from file %s\n\
1148 has the same version (=%d) as the active class but a different checksum.\n\
1149 You should update the version to ClassDef(%s,%d).\n\
1150 Do not try to write objects with the current class definition,\n\
1151 the files will not be readable.\n", GetName(), file->GetName(), fClassVersion, GetName(), fClassVersion + 1);
1153 Warning(
"BuildCheck",
"\n\
1154 The StreamerInfo of class %s \n\
1155 has the same version (=%d) as the active class but a different checksum.\n\
1156 You should update the version to ClassDef(%s,%d).\n\
1157 Do not try to write objects with the current class definition,\n\
1158 the files will not be readable.\n", GetName(), fClassVersion, GetName(), fClassVersion + 1);
1160 CompareContent(fClass,0,kTRUE,kTRUE,file);
1161 fClass->SetBit(TClass::kWarned);
1164 if (!fClass->IsVersioned()) {
1165 Fatal(
"BuildCheck",
"\n\
1166 The StreamerInfo of unversioned class %s \n\
1167 has the same version (=%d) as the active class but an old checksum.\n\
1168 This should not happen. An assert will follow.\n", GetName(), fClassVersion);
1172 if (!fClass->IsLoaded() && this->fOnFileClassVersion>1)
1174 ROOT::ResetClassVersion(fClass,(
const char*)-1, this->fClassVersion);
1180 if (TestBit(kIgnoreTObjectStreamer)) {
1181 fClass->IgnoreTObjectStreamer();
1183 if ((fClassVersion < -1) || (fClassVersion > 65000)) {
1184 printf(
"ERROR reading TStreamerInfo: %s fClassVersion=%d\n", GetName(), fClassVersion);
1190 if (!fClass->TestBit(TClass::kWarned)
1191 && fClass->GetState() >= TClass::kInterpreted
1192 && GetCheckSum() != fClass->GetCheckSum()
1193 && fClassVersion == fClass->GetClassVersion()) {
1197 auto maininfo = fClass->GetStreamerInfo();
1199 fNumber = maininfo->GetNumber();
1205 fClass->RegisterStreamerInfo(
this);
1213 TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
1214 infos->AddAtAndExpand(
this, fNumber);
1220 void TStreamerInfo::BuildEmulated(TFile *file)
1222 R__LOCKGUARD(gInterpreterMutex);
1226 Int_t fv = file->GetVersion()%100000;
1227 R__ASSERT(fv < 30000);
1230 TObjArray *elements = GetElements();
1231 Int_t ndata = elements ? elements->GetEntries() : 0;
1232 for (Int_t i=0;i < ndata;i++) {
1233 TStreamerElement *element = (TStreamerElement*)elements->UncheckedAt(i);
1234 if (!element)
break;
1235 int ty = element->GetType();
1236 if (ty < kChar || ty >kULong+kOffsetL)
continue;
1237 if (ty == kLong) element->SetType(kInt);
1238 if (ty == kULong) element->SetType(kUInt);
1239 if (ty == kLong + kOffsetL) element->SetType(kInt + kOffsetL);
1240 if (ty == kULong + kOffsetL) element->SetType(kUInt + kOffsetL);
1241 if (ty <= kULong)
continue;
1242 duName = element->GetName();
1243 duName.Append(
"QWERTY");
1244 TStreamerBasicType *bt =
new TStreamerBasicType(duName,
"", 0, kInt,
"Int_t");
1245 {
for (
int j=ndata-1;j>=i;j--) {elements->AddAtAndExpand(elements->At(j),j+1);}}
1246 elements->AddAt(bt,i);
1257 Bool_t TStreamerInfo::BuildFor(
const TClass *in_memory_cl )
1259 R__LOCKGUARD(gInterpreterMutex);
1261 if( !in_memory_cl || !in_memory_cl->GetSchemaRules() ) {
1265 auto rules = in_memory_cl->GetSchemaRules()->FindRules( GetName(), fOnFileClassVersion, fCheckSum );
1267 if( rules.empty() && !in_memory_cl->GetCollectionType() ) {
1268 Warning(
"BuildFor",
"The build of %s streamer info for %s has been requested, but no matching conversion rules were specified", GetName(), in_memory_cl->GetName() );
1272 fClass =
const_cast<TClass*
>(in_memory_cl);
1281 Bool_t ClassWasMovedToNamespace(TClass *oldClass, TClass *newClass)
1286 if (oldClass == 0 || newClass == 0)
return kFALSE;
1288 UInt_t newlen = strlen(newClass->GetName());
1289 UInt_t oldlen = strlen(oldClass->GetName());
1291 const char *oldname = oldClass->GetName();
1292 for (UInt_t i = oldlen, done =
false, nest = 0; (i>0) && !done ; --i) {
1293 switch (oldClass->GetName()[i-1]) {
1294 case '>' : ++nest;
break;
1295 case '<' :
if (nest==0)
return kFALSE;
1297 case ':' :
if (nest == 0) oldname= &(oldClass->GetName()[i]); done = kTRUE;
break;
1300 oldlen = strlen(oldname);
1301 if (!(strlen(newClass->GetName()) > strlen(oldClass->GetName()))) {
1305 const char* newEnd = & (newClass->GetName()[newlen-oldlen]);
1307 if (0 != strcmp(newEnd, oldname)) {
1311 Int_t oldv = oldClass->GetStreamerInfo()->GetClassVersion();
1313 if (newClass->GetStreamerInfos() && oldv < newClass->GetStreamerInfos()->GetSize() && newClass->GetStreamerInfos()->At(oldv) && strcmp(newClass->GetStreamerInfos()->At(oldv)->GetName(), oldClass->GetName()) != 0) {
1328 Int_t ImportStreamerInfo(TClass *oldClass, TClass *newClass) {
1330 TIter next(oldClass->GetStreamerInfos());
1331 TStreamerInfo *info;
1332 while ((info = (TStreamerInfo*)next())) {
1333 info = (TStreamerInfo*)info->Clone();
1335 Error(
"ImportStreamerInfo",
"Unable to clone the StreamerInfo for %s.",(*next)->GetName());
1337 info->SetClass(newClass);
1338 Int_t oldv = info->GetClassVersion();
1339 if (oldv > newClass->GetStreamerInfos()->GetSize() || newClass->GetStreamerInfos()->At(oldv) == 0) {
1341 newClass->RegisterStreamerInfo(info);
1346 if (strcmp(newClass->GetStreamerInfos()->At(oldv)->GetName(),
1347 oldClass->GetName()) != 0) {
1358 Bool_t ContainerMatchTClonesArray(TClass *newClass)
1363 return newClass->GetCollectionProxy()
1364 && newClass->GetCollectionProxy()->GetValueClass()
1365 && !newClass->GetCollectionProxy()->HasPointers();
1368 Bool_t CollectionMatch(
const TClass *oldClass,
const TClass* newClass)
1373 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1374 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1376 TClass *oldContent = oldProxy->GetValueClass();
1377 TClass *newContent = newProxy->GetValueClass();
1379 Bool_t contentMatch = kFALSE;
1381 if (oldContent == newContent) {
1382 contentMatch = kTRUE;
1383 }
else if (newContent) {
1384 TString oldFlatContent( TMakeProject::UpdateAssociativeToVector(oldContent->GetName()) );
1385 TString newFlatContent( TMakeProject::UpdateAssociativeToVector(newContent->GetName()) );
1386 if (oldFlatContent == newFlatContent) {
1387 contentMatch = kTRUE;
1390 contentMatch = kFALSE;
1393 contentMatch = (newContent==0);
1397 if ((oldContent==0 && oldProxy->GetType() == newProxy->GetType())
1398 ||(oldContent && oldProxy->HasPointers() == newProxy->HasPointers())) {
1406 Bool_t CollectionMatchFloat16(
const TClass *oldClass,
const TClass* newClass)
1411 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1412 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1414 if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
1415 && (oldProxy->GetType() == kFloat_t || oldProxy->GetType() == kFloat16_t)
1416 && (newProxy->GetType() == kFloat_t || newProxy->GetType() == kFloat16_t )) {
1418 return (oldClass->GetCollectionType() == newClass->GetCollectionType());
1423 Bool_t CollectionMatchDouble32(
const TClass *oldClass,
const TClass* newClass)
1428 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1429 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1431 if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
1432 && (oldProxy->GetType() == kDouble_t || oldProxy->GetType() == kDouble32_t)
1433 && (newProxy->GetType() == kDouble_t || newProxy->GetType() == kDouble32_t )) {
1435 return (oldClass->GetCollectionType() == newClass->GetCollectionType());
1440 Bool_t CollectionMatchLong64(
const TClass *oldClass,
const TClass* newClass)
1445 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1446 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1448 if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
1449 && (oldProxy->GetType() == kLong_t || oldProxy->GetType() == kLong64_t)
1450 && (newProxy->GetType() == kLong_t || newProxy->GetType() == kLong64_t )) {
1452 return (oldClass->GetCollectionType() == newClass->GetCollectionType());
1457 Bool_t CollectionMatchULong64(
const TClass *oldClass,
const TClass* newClass)
1462 TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
1463 TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
1465 if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
1466 && (oldProxy->GetType() == kULong_t || oldProxy->GetType() == kULong64_t)
1467 && (newProxy->GetType() == kULong_t || newProxy->GetType() == kULong64_t )) {
1469 return (oldClass->GetCollectionType() == newClass->GetCollectionType());
1474 TClass *FindAlternate(TClass *context,
const std::string &i_name, std::string& newName)
1480 std::string name(i_name);
1482 if (name.compare(0,6,
"const ")==0) {
1488 while(name[name.length()-nstars-1]==
'*') {
1493 name.erase(name.length()-nstars,nstars);
1496 std::string alternate(context->GetName());
1497 alternate.append(
"::");
1498 alternate.append(name);
1500 TClass *altcl = TClass::GetClass(alternate.c_str(),
false,
true);
1502 newName.append(altcl->GetName());
1503 newName.append(suffix);
1507 size_t ctxt_cursor = strlen(context->GetName());
1508 for (
size_t level = 0; ctxt_cursor != 0; --ctxt_cursor) {
1509 switch (context->GetName()[ctxt_cursor]) {
1510 case '<': --level;
break;
1511 case '>': ++level;
break;
1512 case ':':
if (level == 0) {
1516 alternate.append(context->GetName(),ctxt_cursor+1);
1517 alternate.append(name);
1518 altcl = TClass::GetClass(alternate.c_str(),
false,
true);
1520 newName.append(altcl->GetName());
1521 newName.append(suffix);
1531 TClass *FixCollectionV5(TClass *context, TClass *oldClass, TClass *newClass)
1533 assert(oldClass->GetCollectionProxy() && newClass->GetCollectionProxy());
1535 TVirtualCollectionProxy *old = oldClass->GetCollectionProxy();
1536 TVirtualCollectionProxy *current = newClass->GetCollectionProxy();
1537 Int_t stlkind = old->GetCollectionType();
1539 if (stlkind == ROOT::kSTLmap || stlkind == ROOT::kSTLmultimap) {
1541 if (current->GetValueClass() ==
nullptr) {
1549 TVirtualStreamerInfo *info = current->GetValueClass()->GetStreamerInfo();
1550 if (info->GetElements()->GetEntries() != 2) {
1553 TStreamerElement *f = (TStreamerElement*) info->GetElements()->At(0);
1554 TStreamerElement *s = (TStreamerElement*) info->GetElements()->At(1);
1556 info = old->GetValueClass()->GetStreamerInfo();
1557 assert(info->GetElements()->GetEntries() == 2);
1558 TStreamerElement *of = (TStreamerElement*) info->GetElements()->At(0);
1559 TStreamerElement *os = (TStreamerElement*) info->GetElements()->At(1);
1561 TClass *firstNewCl = f ? f->GetClass() : 0;
1562 TClass *secondNewCl = s ? s->GetClass() : 0;
1564 TClass *firstOldCl = of ? of->GetClass() : 0;
1565 TClass *secondOldCl = os ? os->GetClass() : 0;
1567 if ((firstNewCl && !firstOldCl) || (secondNewCl && !secondOldCl))
1569 std::vector<std::string> inside;
1571 TClassEdit::GetSplit( oldClass->GetName(), inside, nestedLoc, TClassEdit::kLong64 );
1573 TClass *firstAltCl = firstOldCl;
1574 TClass *secondAltCl = secondOldCl;
1575 std::string firstNewName;
1576 std::string secondNewName;
1577 if (firstNewCl && !firstOldCl) {
1578 firstAltCl = FindAlternate(context, inside[1], firstNewName);
1579 }
else if (firstAltCl) {
1580 firstNewName = firstAltCl->GetName();
1582 firstNewName = inside[1];
1584 if (secondNewCl && !secondOldCl) {
1585 secondAltCl = FindAlternate(context, inside[2], secondNewName);
1586 }
else if (secondAltCl) {
1587 secondNewName = secondAltCl->GetName();
1589 secondNewName = inside[2];
1591 if ((firstNewCl && firstAltCl != firstOldCl) ||
1592 (secondNewCl && secondAltCl != secondOldCl) ) {
1595 std::string alternate = inside[0];
1596 alternate.append(
"<");
1597 alternate.append(firstNewName);
1598 alternate.append(
",");
1599 alternate.append(secondNewName);
1603 if (alternate[alternate.length()-1]==
'>') {
1604 alternate.append(
" ");
1606 alternate.append(
">");
1607 return TClass::GetClass(alternate.c_str(),
true,
true);
1611 }
else if (current->GetValueClass() && !old->GetValueClass()
1612 && old->GetType() == kInt_t) {
1619 std::vector<std::string> inside;
1621 TClassEdit::GetSplit( oldClass->GetName(), inside, nestedLoc, TClassEdit::kLong64 );
1624 std::string newName;
1625 TClass *altcl = FindAlternate(context, inside[1], newName);
1628 std::string alternate = inside[0];
1629 alternate.append(
"<");
1630 alternate.append(newName);
1634 if (alternate[alternate.length()-1]==
'>') {
1635 alternate.append(
" ");
1637 alternate.append(
">");
1638 return TClass::GetClass(alternate.c_str(),
true,
true);
1645 struct TBuildOldGuard {
1646 TBuildOldGuard(TStreamerInfo* info): fInfo(info) {
1647 fInfo->SetBit(TStreamerInfo::kBuildRunning);
1650 fInfo->ResetBit(TStreamerInfo::kBuildRunning);
1651 fInfo->SetBit(TStreamerInfo::kBuildOldUsed);
1653 TStreamerInfo* fInfo;
1660 void TStreamerInfo::BuildOld()
1662 R__LOCKGUARD(gInterpreterMutex);
1664 if ( TestBit(kBuildOldUsed) )
return;
1667 if (TestBit(TStreamerInfo::kBuildRunning))
return;
1671 TBuildOldGuard buildOldGuard(
this);
1674 printf(
"\n====>Rebuilding TStreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
1677 Bool_t wasCompiled = IsCompiled();
1679 if (fClass->GetClassVersion() == fClassVersion) {
1680 if (!fClass->HasInterpreterInfo() || fClass->GetCollectionType() || TClassEdit::IsSTLBitset(GetName()))
1686 fClass->BuildRealData();
1710 fClass->GetStreamerInfo();
1713 TIter next(fElements);
1714 TStreamerElement* element;
1716 TMemberStreamer* streamer = 0;
1718 constexpr
size_t kSizeOfPtr =
sizeof(
void*);
1722 if ((fElements->GetEntries() == 1) && !strcmp(fElements->At(0)->GetName(),
"This")) {
1723 if (fClass->GetCollectionProxy()) {
1724 element = (TStreamerElement*)next();
1725 element->SetNewType( element->GetType() );
1726 element->SetNewClass( fClass );
1727 }
else if (((TStreamerElement*)fElements->At(0))->GetType() == TStreamerInfo::kSTL &&
1728 strcmp( ((TStreamerElement*)fElements->At(0))->GetTypeName(),GetName()) != 0) {
1738 TClass *allocClass = 0;
1739 TStreamerInfo *infoalloc = 0;
1745 ROOT::TSchemaRuleSet::TMatches rules;
1746 const ROOT::TSchemaRuleSet* ruleSet = fClass->GetSchemaRules();
1748 if (ruleSet) rules = ruleSet->FindRules( GetName(), fOnFileClassVersion, fCheckSum );
1750 Bool_t shouldHaveInfoLoc = fClass->TestBit(TClass::kIsEmulation) && !TClassEdit::IsStdClass(fClass->GetName());
1751 Int_t virtualInfoLocAlloc = 0;
1752 fNVirtualInfoLoc = 0;
1753 delete [] fVirtualInfoLoc;
1754 fVirtualInfoLoc = 0;
1756 while ((element = (TStreamerElement*) next())) {
1757 if (element->IsA()==TStreamerArtificial::Class()
1758 || element->TestBit(TStreamerElement::kCache) )
1768 element->SetNewType(element->GetType());
1769 if (element->IsBase()) {
1774 if (element->IsA() == TStreamerBase::Class()) {
1775 TStreamerBase* base = (TStreamerBase*) element;
1776 #if defined(PROPER_IMPLEMEMANTION_OF_BASE_CLASS_RENAMING)
1777 TClassRef baseclass = fClass->GetBaseClass( base->GetName() );
1784 TClassRef baseclass = base->GetClassPointer();
1791 if( !baseclass && !fClass->TestBit( TClass::kIsEmulation ) ) {
1792 const ROOT::TSchemaRule* rule = (rules ? rules.GetRuleWithSource( base->GetName() ) : 0);
1799 Error(
"BuildOld",
"Could not find base class: %s for %s and could not find any matching rename rule\n", base->GetName(), GetName());
1807 const TObjArray* targets = rule->GetTarget();
1809 Error(
"BuildOld",
"Could not find base class: %s for %s, renaming rule was found but is malformed\n", base->GetName(), GetName());
1811 TString newBaseClass = ((TObjString*)targets->At(0))->GetString();
1812 baseclass = TClass::GetClass( newBaseClass );
1813 base->SetNewBaseClass( baseclass );
1819 else if( !baseclass ) {
1820 baseclass = base->GetClassPointer();
1822 Warning(
"BuildOld",
"Missing base class: %s skipped", base->GetName());
1824 baseclass =
new TClass(element->GetName(), 1, 0, 0, -1, -1);
1825 element->Update(0, baseclass);
1828 baseclass->BuildRealData();
1832 Int_t baseOffset = fClass->GetBaseClassOffset(baseclass);
1835 if (baseOffset < 0) {
1839 TList* listOfBases = fClass->GetListOfBases();
1842 TIter nextBC(fClass->GetListOfBases());
1843 while ((bc = (TBaseClass*) nextBC())) {
1844 TClass *in_memory_bcl = bc->GetClassPointer();
1845 if (in_memory_bcl && in_memory_bcl->GetSchemaRules()) {
1846 auto baserule = in_memory_bcl->GetSchemaRules()->FindRules( base->GetName(), base->GetBaseVersion(), base->GetBaseCheckSum() );
1847 if (!baserule.empty()) {
1848 base->SetNewBaseClass(in_memory_bcl);
1849 baseOffset = bc->GetDelta();
1858 element->Init(
this);
1862 TStreamerInfo* infobase;
1863 if (fClass->TestBit(TClass::kIsEmulation) && (baseclass->Property() & kIsAbstract)) {
1864 Int_t version = base->GetBaseVersion();
1865 if (version >= 0 || base->GetBaseCheckSum() == 0) {
1866 infobase = (TStreamerInfo*)baseclass->GetStreamerInfoAbstractEmulated(version);
1868 infobase = (TStreamerInfo*)baseclass->FindStreamerInfoAbstractEmulated(base->GetBaseCheckSum());
1870 if (infobase) baseclass = infobase->GetClass();
1873 infobase = (TStreamerInfo*)base->GetBaseStreamerInfo();
1876 if (infobase && infobase->fComp == 0) {
1877 infobase->BuildOld();
1880 if (infobase && shouldHaveInfoLoc && baseclass->TestBit(TClass::kIsEmulation) ) {
1881 if ( (fNVirtualInfoLoc + infobase->fNVirtualInfoLoc) > virtualInfoLocAlloc ) {
1882 ULong_t *store = fVirtualInfoLoc;
1883 virtualInfoLocAlloc = 16 * ( (fNVirtualInfoLoc + infobase->fNVirtualInfoLoc) / 16 + 1);
1884 fVirtualInfoLoc =
new ULong_t[virtualInfoLocAlloc];
1886 memcpy(fVirtualInfoLoc, store,
sizeof(ULong_t)*fNVirtualInfoLoc);
1890 for (
int nloc = 0; nloc < infobase->fNVirtualInfoLoc; ++nloc) {
1891 fVirtualInfoLoc[ fNVirtualInfoLoc + nloc ] = baseOffset + infobase->fVirtualInfoLoc[nloc];
1893 fNVirtualInfoLoc += infobase->fNVirtualInfoLoc;
1898 if (baseOffset < 0) {
1899 element->SetNewType(-1);
1902 element->SetOffset(baseOffset);
1903 offset += baseclass->Size();
1909 TList* listOfBases = fClass->GetListOfBases();
1910 Int_t baseOffset = -1;
1916 TIter nextBC(fClass->GetListOfBases());
1917 while ((bc = (TBaseClass*) nextBC())) {
1918 if (strchr(bc->GetName(),
'<') || !strcmp(bc->GetName(),
"string")) {
1919 TString bcName(TClassEdit::ShortType(bc->GetName(), TClassEdit::kDropStlDefault).c_str());
1920 TString elName(TClassEdit::ShortType(element->GetTypeName(), TClassEdit::kDropStlDefault).c_str());
1921 if (bcName == elName) {
1930 element->SetOffset(kMissing);
1931 element->SetNewType(-1);
1933 }
else if (bc->GetClassPointer()->GetCollectionProxy()
1934 && !bc->GetClassPointer()->IsLoaded()
1935 && bc->GetClassPointer()->GetCollectionProxy()->GetCollectionType() != ROOT::kSTLvector) {
1936 Error(
"BuildOld",
"The class \"%s\" is compiled and its base class \"%s\" is a collection and we do not have a dictionary for it, we will not be able to read or write this base class.",GetName(),bc->GetName());
1938 element->SetOffset(kMissing);
1939 element->SetNewType(-1);
1942 baseOffset = bc->GetDelta();
1943 asize = bc->GetClassPointer()->Size();
1945 }
else if (fClass->TestBit( TClass::kIsEmulation )) {
1948 TStreamerInfo* newInfo = (TStreamerInfo*) fClass->GetStreamerInfos()->At(fClass->GetClassVersion());
1949 if (newInfo ==
this) {
1950 baseOffset = offset;
1951 asize = element->GetSize();
1952 }
else if (newInfo) {
1953 TIter newElems( newInfo->GetElements() );
1954 TStreamerElement *newElement;
1955 while( (newElement = (TStreamerElement*)newElems()) ) {
1956 const char *newElName = newElement->GetName();
1957 if (newElement->IsBase() && (strchr(newElName,
'<') || !strcmp(newElName,
"string")) ) {
1958 TString bcName(TClassEdit::ShortType(newElName, TClassEdit::kDropStlDefault).c_str());
1959 TString elName(TClassEdit::ShortType(element->GetTypeName(), TClassEdit::kDropStlDefault).c_str());
1960 if (bcName == elName) {
1966 Error(
"BuildOld",
"Could not find STL base class: %s for %s\n", element->GetName(), GetName());
1969 baseOffset = newElement->GetOffset();
1970 asize = newElement->GetSize();
1973 if (baseOffset == -1) {
1974 TClass* cb = element->GetClassPointer();
1976 element->SetNewType(-1);
1980 baseOffset = fClass->GetBaseClassOffset(cb);
1984 if (baseOffset < 0) {
1985 element->SetNewType(-1);
1988 element->SetOffset(baseOffset);
1990 element->Init(
this);
1996 if (shouldHaveInfoLoc && fNVirtualInfoLoc==0) {
1997 fNVirtualInfoLoc = 1;
1998 fVirtualInfoLoc =
new ULong_t[1];
1999 fVirtualInfoLoc[0] = offset;
2000 offset +=
sizeof(TStreamerInfo*);
2003 TDataMember* dm = 0;
2005 std::string typeNameBuf;
2006 const char* dmType =
nullptr;
2007 Bool_t dmIsPtr =
false;
2008 TDataType* dt(
nullptr);
2010 std::array<Int_t, 5> maxIndices;
2011 Bool_t isStdArray(kFALSE);
2014 if (fClass->GetState() <= TClass::kEmulated) {
2021 element->Init(
this);
2029 dm = (TDataMember*) fClass->GetListOfDataMembers()->FindObject(element->GetName());
2030 if (dm && dm->IsPersistent()) {
2031 fClass->BuildRealData();
2033 offset = GetDataMemberOffset(dm, streamer);
2034 element->SetOffset(offset);
2035 element->Init(
this);
2038 dmType = dm->GetTypeName();
2039 dmIsPtr = dm->IsaPointer();
2041 typeNameBuf = TClassEdit::GetNameForIO(dmType, TClassEdit::EModType::kNone, &nameChanged);
2043 dmIsPtr = TClassEdit::IsUniquePtr(dmType);
2044 dmType = typeNameBuf.c_str();
2046 if ((isStdArray = TClassEdit::IsStdArray(dmType))){
2047 TClassEdit::GetStdArrayProperties(dmType,
2051 dmType = typeNameBuf.c_str();
2052 dt = gROOT->GetType(dmType);
2057 TString dmClassName = TClassEdit::ShortType(dmType,TClassEdit::kDropStlDefault).c_str();
2058 dmClassName = dmClassName.Strip(TString::kTrailing,
'*');
2059 if (dmClassName.Index(
"const ")==0) dmClassName.Remove(0,6);
2060 TClass *elemDm = ! (dt || dm->IsBasic()) ? TClass::GetClass(dmClassName.Data()) : 0;
2061 if (elemDm && elemDm->GetCollectionProxy()
2062 && !elemDm->IsLoaded()
2063 && elemDm->GetCollectionProxy()->GetCollectionType() != ROOT::kSTLvector) {
2064 Error(
"BuildOld",
"The class \"%s\" is compiled and for its data member \"%s\", we do not have a dictionary for the collection \"%s\", we will not be able to read or write this data member.",GetName(),dm->GetName(),elemDm->GetName());
2066 element->SetOffset(kMissing);
2067 element->SetNewType(-1);
2069 element->SetStreamer(streamer);
2070 int narr = element->GetArrayLength();
2074 int dsize = dm->GetUnitSize();
2075 element->SetSize(dsize*narr);
2078 TRealData* rd = fClass->GetRealData(element->GetName());
2079 if (rd && rd->GetDataMember()) {
2080 element->SetOffset(rd->GetThisOffset());
2081 element->Init(
this);
2082 dm = rd->GetDataMember();
2083 dmType = dm->GetTypeName();
2084 dmIsPtr = dm->IsaPointer();
2085 int narr = element->GetArrayLength();
2089 int dsize = dm->GetUnitSize();
2090 element->SetSize(dsize*narr);
2099 if (dm && dm->IsPersistent()) {
2100 auto theType = isStdArray ? dt : dm->GetDataType();
2102 Bool_t isArray = isStdArray || element->GetArrayLength() >= 1;
2103 Bool_t hasCount = element->HasCounter();
2105 if ((fClass == TObject::Class()) && !strcmp(dm->GetName(),
"fBits")) {
2110 newType = (EReadWrite)theType->GetType();
2112 if ((newType == ::kChar_t) && dmIsPtr && !isArray && !hasCount) {
2113 newType = ::kCharStar;
2114 }
else if (dmIsPtr) {
2115 newType += kOffsetP;
2116 }
else if (isArray) {
2117 newType += kOffsetL;
2120 if (newType == -1) {
2121 newClass = TClass::GetClass(dmType);
2125 if (!fClass->IsLoaded()) {
2126 TStreamerInfo* newInfo = (TStreamerInfo*) fClass->GetStreamerInfos()->At(fClass->GetClassVersion());
2127 if (newInfo && (newInfo !=
this)) {
2128 TStreamerElement* newElems = (TStreamerElement*) newInfo->GetElements()->FindObject(element->GetName());
2129 newClass = newElems ? newElems->GetClassPointer() : 0;
2130 if (newClass == 0) {
2131 newType = newElems ? newElems->GetType() : -1;
2132 if (!(newType < kObject)) {
2138 newClass = element->GetClassPointer();
2139 if (newClass.GetClass() == 0) {
2140 newType = element->GetType();
2141 if (!(newType < kObject)) {
2152 if (element->GetType() >= TStreamerInfo::kObject) {
2154 element->SetNewType(-2);
2155 }
else if (element->GetType() != newType) {
2156 element->SetNewType(newType);
2159 Info(
"BuildOld",
"element: %s %s::%s has new type: %s/%d", element->GetTypeName(), GetName(), element->GetName(), dm ? dm->GetFullTypeName() : TDataType::GetTypeName((EDataType)newType), newType);
2162 }
else if (newClass.GetClass()) {
2167 TClass* oldClass = TClass::GetClass(TClassEdit::ShortType(element->GetTypeName(), TClassEdit::kDropTrailStar).c_str());
2168 if (oldClass == newClass.GetClass()) {
2170 }
else if (ClassWasMovedToNamespace(oldClass, newClass.GetClass())) {
2172 if (0 != (oldv = ImportStreamerInfo(oldClass, newClass.GetClass()))) {
2173 Warning(
"BuildOld",
"Can not properly load the TStreamerInfo from %s into %s due to a conflict for the class version %d", oldClass->GetName(), newClass->GetName(), oldv);
2175 element->SetTypeName(newClass->GetName());
2177 Warning(
"BuildOld",
"element: %s::%s %s has new type %s", GetName(), element->GetTypeName(), element->GetName(), newClass->GetName());
2180 }
else if (oldClass == TClonesArray::Class()) {
2181 if (ContainerMatchTClonesArray(newClass.GetClass())) {
2182 Int_t elemType = element->GetType();
2183 Bool_t isPrealloc = (elemType == kObjectp) || (elemType == kAnyp) || (elemType == (kObjectp + kOffsetL)) || (elemType == (kAnyp + kOffsetL));
2184 element->Update(oldClass, newClass.GetClass());
2185 TVirtualCollectionProxy *cp = newClass->GetCollectionProxy();
2186 TConvertClonesArrayToProxy *ms =
new TConvertClonesArrayToProxy(cp, element->IsaPointer(), isPrealloc);
2187 element->SetStreamer(ms);
2192 if (element->GetType() == kObject) {
2193 element->SetNewType(kAny);
2194 element->SetType(kAny);
2197 Warning(
"BuildOld",
"element: %s::%s %s has new type %s", GetName(), element->GetTypeName(), element->GetName(), newClass->GetName());
2200 element->SetNewType(-2);
2202 }
else if (oldClass && oldClass->GetCollectionProxy() && newClass->GetCollectionProxy()) {
2204 TClass *oldFixedClass = FixCollectionV5(GetClass(),oldClass,newClass);
2205 if (oldFixedClass && oldFixedClass != oldClass) {
2206 element->Update(oldClass,oldFixedClass);
2207 oldClass = oldFixedClass;
2210 if (CollectionMatch(oldClass, newClass)) {
2211 Int_t oldkind = oldClass->GetCollectionType();
2212 Int_t newkind = newClass->GetCollectionType();
2214 if ( (oldkind==ROOT::kSTLmap || oldkind==ROOT::kSTLmultimap) &&
2215 (newkind!=ROOT::kSTLmap && newkind!=ROOT::kSTLmultimap) ) {
2217 Int_t elemType = element->GetType();
2218 Bool_t isPrealloc = (elemType == kObjectp) || (elemType == kAnyp) || (elemType == (kObjectp + kOffsetL)) || (elemType == (kAnyp + kOffsetL));
2220 TClassStreamer *streamer2 = newClass->GetStreamer();
2222 TConvertMapToProxy *ms =
new TConvertMapToProxy(streamer2, element->IsaPointer(), isPrealloc);
2223 if (ms && ms->IsValid()) {
2224 element->SetStreamer(ms);
2225 switch( element->GetType() ) {
2227 case TStreamerInfo::kSTLp:
2228 case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL:
2229 element->SetNewType(-2);
2231 case TStreamerInfo::kSTL:
2232 case TStreamerInfo::kSTL + TStreamerInfo::kOffsetL:
2239 element->Update(oldClass, newClass.GetClass());
2241 }
else if ( (newkind==ROOT::kSTLmap || newkind==ROOT::kSTLmultimap) &&
2242 (oldkind!=ROOT::kSTLmap && oldkind!=ROOT::kSTLmultimap) ) {
2243 element->SetNewType(-2);
2245 element->Update(oldClass, newClass.GetClass());
2249 Warning(
"BuildOld",
"element: %s::%s %s has new type %s", GetName(), element->GetTypeName(), element->GetName(), newClass->GetName());
2251 }
else if (CollectionMatchFloat16(oldClass,newClass)) {
2253 }
else if (CollectionMatchDouble32(oldClass,newClass)) {
2255 }
else if (CollectionMatchLong64(oldClass,newClass)) {
2257 element->Update(oldClass, newClass.GetClass());
2258 }
else if (CollectionMatchULong64(oldClass,newClass)) {
2260 element->Update(oldClass, newClass.GetClass());
2261 }
else if (newClass->GetSchemaRules()->HasRuleWithSourceClass( oldClass->GetName() )) {
2266 element->SetNewClass( newClass );
2268 element->SetNewType(-2);
2271 }
else if(oldClass &&
2272 newClass.GetClass() &&
2273 newClass->GetSchemaRules() &&
2274 newClass->GetSchemaRules()->HasRuleWithSourceClass( oldClass->GetName() ) ) {
2279 element->SetNewClass( newClass );
2281 element->SetNewType(-2);
2284 Bool_t cannotConvert = kFALSE;
2285 if (element->GetNewType() != -2) {
2288 if (strncmp(dm->GetTitle(),
"->",2)==0) {
2290 if (newClass->IsTObject()) {
2292 }
else if (newClass->GetCollectionProxy()) {
2298 if (TClass::GetClass(dm->GetTypeName())->IsTObject()) {
2300 }
else if (newClass->GetCollectionProxy()) {
2307 if (newClass->GetCollectionProxy()) {
2309 }
else if (newClass == TString::Class()) {
2311 }
else if (newClass == TObject::Class()) {
2313 }
else if (newClass == TNamed::Class()) {
2315 }
else if (newClass->IsTObject()) {
2321 if ((!dmIsPtr || newType==kSTLp) && (isStdArray ? ndim : dm->GetArrayDim()) > 0) {
2322 newType += kOffsetL;
2324 }
else if (!fClass->IsLoaded()) {
2325 TStreamerInfo* newInfo = (TStreamerInfo*) fClass->GetStreamerInfos()->At(fClass->GetClassVersion());
2326 if (newInfo && (newInfo !=
this)) {
2327 TStreamerElement* newElems = (TStreamerElement*) newInfo->GetElements()->FindObject(element->GetName());
2329 newType = newElems->GetType();
2332 newType = element->GetType();
2335 if (element->GetType() == kSTL
2336 || ((element->GetType() == kObject || element->GetType() == kAny || element->GetType() == kObjectp || element->GetType() == kAnyp)
2337 && oldClass == TClonesArray::Class()))
2339 cannotConvert = (newType != kSTL && newType != kObject && newType != kAny && newType != kSTLp && newType != kObjectp && newType != kAnyp);
2341 }
else if (element->GetType() == kSTLp || ((element->GetType() == kObjectP || element->GetType() == kAnyP) && oldClass == TClonesArray::Class()) )
2343 cannotConvert = (newType != kSTL && newType != kObject && newType != kAny && newType != kSTLp && newType != kObjectP && newType != kAnyP);
2345 }
else if (element->GetType() == kSTL + kOffsetL
2346 || ((element->GetType() == kObject + kOffsetL|| element->GetType() == kAny + kOffsetL|| element->GetType() == kObjectp+ kOffsetL || element->GetType() == kAnyp+ kOffsetL)
2347 && oldClass == TClonesArray::Class()))
2349 cannotConvert = (newType != kSTL + kOffsetL && newType != kObject+ kOffsetL && newType != kAny+ kOffsetL && newType != kSTLp+ kOffsetL && newType != kObjectp+ kOffsetL && newType != kAnyp+ kOffsetL);
2351 }
else if (element->GetType() == kSTLp + kOffsetL || ((element->GetType() == kObjectP+ kOffsetL || element->GetType() == kAnyP+ kOffsetL) && oldClass == TClonesArray::Class()) )
2353 cannotConvert = (newType != kSTL+ kOffsetL && newType != kObject+ kOffsetL && newType != kAny+ kOffsetL && newType != kSTLp + kOffsetL&& newType != kObjectP+ kOffsetL && newType != kAnyP+ kOffsetL);
2355 }
else if ((element->GetType() == kObjectp || element->GetType() == kAnyp
2356 || element->GetType() == kObject || element->GetType() == kAny
2357 || element->GetType() == kTObject || element->GetType() == kTNamed || element->GetType() == kTString )) {
2360 if (newType != -1) {
2361 if (newType == kObjectp || newType == kAnyp
2362 || newType == kObject || newType == kAny
2363 || newType == kTObject || newType == kTNamed || newType == kTString) {
2365 element->SetNewType(newType);
2368 cannotConvert = kTRUE;
2372 printf(
"%s We have no clue\n", dm->GetName());
2373 cannotConvert = kTRUE;
2375 }
else if (element->GetType() == kObjectP || element->GetType() == kAnyP) {
2376 if (newType != -1) {
2377 if (newType == kObjectP || newType == kAnyP ) {
2380 cannotConvert = kTRUE;
2384 cannotConvert = kTRUE;
2388 if (cannotConvert) {
2389 element->SetNewType(-2);
2392 Info(
"BuildOld",
"element: %s %s::%s has new type: %s/%d", element->GetTypeName(), GetName(), element->GetName(), dm ? dm->GetFullTypeName() : TDataType::GetTypeName((EDataType)newType), newType);
2396 element->SetNewType(-1);
2398 element->SetOffset(kMissing);
2401 if (offset != kMissing && fClass->GetState() <= TClass::kEmulated) {
2410 if (element->GetType() == TStreamerInfo::kSTL &&
2411 strcmp(element->GetName(),
"This") == 0 &&
2412 strcmp(element->GetTypeName(),GetName()) == 0 &&
2413 !fClass->GetCollectionProxy()) {
2417 asize =
sizeof(std::vector<int>);
2420 asize = element->GetSize();
2423 if ((offset % kSizeOfPtr) != 0) {
2424 offset = offset - (offset % kSizeOfPtr) + kSizeOfPtr;
2426 element->SetOffset(offset);
2430 if (!wasCompiled && rules) {
2431 if (rules.HasRuleWithSource( element->GetName(), kTRUE ) ) {
2433 if (allocClass == 0) {
2434 infoalloc = (TStreamerInfo *)Clone(TString::Format(
"%s@@%d",GetName(),GetOnFileClassVersion()));
2436 Error(
"BuildOld",
"Unable to create the StreamerInfo for %s.",TString::Format(
"%s@@%d",GetName(),GetOnFileClassVersion()).Data());
2438 infoalloc->SetBit(kBuildOldUsed,
false);
2439 infoalloc->BuildCheck();
2440 infoalloc->BuildOld();
2441 allocClass = infoalloc->GetClass();
2446 if (element->GetNewType()>0
2447 && !rules.HasRuleWithTarget( element->GetName(), kTRUE ) ) {
2449 TStreamerElement *copy = (TStreamerElement*)element->Clone();
2450 R__TObjArray_InsertBefore( fElements, copy, element );
2452 copy->SetBit(TStreamerElement::kRepeat);
2459 TStreamerElement *writecopy = (TStreamerElement*)element->Clone();
2460 R__TObjArray_InsertAfter( fElements, writecopy, element );
2462 writecopy->SetBit(TStreamerElement::kWrite);
2463 writecopy->SetNewType( writecopy->GetType() );
2464 writecopy->SetOffset(element->GetOffset());
2466 element->SetBit(TStreamerElement::kCache);
2467 element->SetNewType( element->GetType() );
2468 element->SetOffset(infoalloc ? infoalloc->GetOffset(element->GetName()) : 0);
2469 }
else if (rules.HasRuleWithTarget( element->GetName(), kTRUE ) ) {
2473 if (element->GetType() == kCounter) {
2478 element->SetOffset(kMissing);
2481 }
else if (rules && rules.HasRuleWithTarget( element->GetName(), kTRUE ) ) {
2485 if (element->GetType() == kCounter) {
2490 element->SetOffset(kMissing);
2494 if (element->GetNewType() == -2) {
2495 Warning(
"BuildOld",
"Cannot convert %s::%s from type: %s to type: %s, skip element", GetName(), element->GetName(), element->GetTypeName(), newClass ? newClass->GetName() : (dm ? dm->GetFullTypeName() :
"unknown") );
2501 if (shouldHaveInfoLoc && fNVirtualInfoLoc==0) {
2502 fNVirtualInfoLoc = 1;
2503 fVirtualInfoLoc =
new ULong_t[1];
2504 fVirtualInfoLoc[0] = offset;
2505 offset +=
sizeof(TStreamerInfo*);
2509 if ((fOldVersion <= 2) && nBaze) {
2511 TObjArray& arr = *fElements;
2512 TObjArray tai(nBaze);
2513 int narr = arr.GetLast() + 1;
2517 for (iel = 0; iel < narr; ++iel) {
2518 element = (TStreamerElement*) arr[iel];
2519 if (element->IsBase() && (element->IsA() != TStreamerBase::Class())) {
2520 tai[kel++] = element;
2522 arr[jel++] = element;
2525 for (kel = 0; jel < narr;) {
2526 arr[jel++] = tai[kel++];
2531 if (!wasCompiled) InsertArtificialElements(rules);
2533 if (!wasCompiled && allocClass) {
2535 TStreamerElement *el =
new TStreamerArtificial(
"@@alloc",
"", 0, TStreamerInfo::kCacheNew, allocClass->GetName());
2536 R__TObjArray_InsertAt( fElements, el, 0 );
2538 el =
new TStreamerArtificial(
"@@dealloc",
"", 0, TStreamerInfo::kCacheDelete, allocClass->GetName());
2539 fElements->Add( el );
2549 void TStreamerInfo::Clear(Option_t *option)
2551 TString opt = option;
2554 if (opt.Contains(
"build")) {
2555 R__LOCKGUARD(gInterpreterMutex);
2557 delete [] fComp; fComp = 0;
2558 delete [] fCompFull; fCompFull= 0;
2559 delete [] fCompOpt; fCompOpt = 0;
2565 ResetBit(kBuildOldUsed);
2567 if (fReadObjectWise) fReadObjectWise->fActions.clear();
2568 if (fReadMemberWise) fReadMemberWise->fActions.clear();
2569 if (fReadMemberWiseVecPtr) fReadMemberWiseVecPtr->fActions.clear();
2570 if (fReadText) fReadText->fActions.clear();
2571 if (fWriteObjectWise) fWriteObjectWise->fActions.clear();
2572 if (fWriteMemberWise) fWriteMemberWise->fActions.clear();
2573 if (fWriteMemberWiseVecPtr) fWriteMemberWiseVecPtr->fActions.clear();
2574 if (fWriteText) fWriteText->fActions.clear();
2590 TMemberInfo(TClass *parent) : fParent(parent) {};
2592 void SetDataType(Int_t datatype) {
2593 fDataType = datatype;
2596 void SetName(
const char *name) {
2599 void SetClassName(
const char *name) {
2600 fClassName = TClassEdit::ResolveTypedef(TClassEdit::ShortType( name, TClassEdit::kDropStlDefault | TClassEdit::kDropStd ).c_str(),kTRUE);
2602 void SetComment(
const char *title) {
2603 const char *left = strstr(title,
"[");
2605 const char *right = strstr(left,
"]");
2608 fComment.Append(left,right-left);
2625 Bool_t operator!=(
const TMemberInfo &other) {
2626 if (fName != other.fName)
return kTRUE;
2627 if (fDataType < TStreamerInfo::kObject) {
2629 if (fDataType != other.fDataType) {
2630 if ( (fDataType == 4 && other.fDataType == 16)
2631 || (fDataType == 16 && other.fDataType == 4) ) {
2633 }
else if ( (fDataType == 14 && other.fDataType == 17)
2634 || (fDataType == 17 && other.fDataType == 14) ) {
2636 }
else if ( (fDataType == 3 && other.fDataType == 6)
2637 ||(fDataType == 6 && other.fDataType == 3) ){
2646 }
else if (fClassName != other.fClassName) {
2647 if ( (fClassName ==
"long" && (other.fClassName ==
"long long" || other.fClassName ==
"Long64_t"))
2648 || ( (fClassName ==
"long long" || fClassName ==
"Long64_t") && other.fClassName ==
"long") ) {
2650 }
else if ( (fClassName ==
"unsigned long" && (other.fClassName ==
"unsigned long long" || other.fClassName ==
"ULong64_t"))
2651 || ( (fClassName ==
"unsigned long long" || fClassName ==
"ULong64_t") && other.fClassName ==
"unsigned long") ) {
2653 }
else if (TClassEdit::IsSTLCont(fClassName)) {
2654 TString name = TClassEdit::ShortType( fClassName, TClassEdit::kDropStlDefault );
2655 TString othername = TClassEdit::ShortType( other.fClassName, TClassEdit::kDropStlDefault );
2656 if (name != othername) {
2657 TClass *cl = TClass::GetClass(name);
2658 TClass *otherCl = TClass::GetClass(othername);
2659 if (!CollectionMatch(cl,otherCl)) {
2660 TClass *oldFixedClass = FixCollectionV5(fParent,cl,otherCl);
2661 if (!oldFixedClass || !CollectionMatch(oldFixedClass,otherCl)) {
2670 return fComment != other.fComment;
2678 void TStreamerInfo::CallShowMembers(
const void* obj, TMemberInspector &insp, Bool_t isTransient)
const
2680 TIter next(fElements);
2681 TStreamerElement* element = (TStreamerElement*) next();
2683 TString elementName;
2685 for (; element; element = (TStreamerElement*) next()) {
2688 if (element->GetOffset() == kMissing) {
2692 char* eaddr = ((
char*)obj) + element->GetOffset();
2694 if (element->IsBase()) {
2696 }
else if (element->IsaPointer()) {
2697 elementName.Form(
"*%s",element->GetFullName());
2698 insp.Inspect(fClass, insp.GetParent(), elementName.Data(), eaddr, isTransient);
2700 insp.Inspect(fClass, insp.GetParent(), element->GetFullName(), eaddr, isTransient);
2701 Int_t etype = element->GetType();
2710 TClass *ecl = element->GetClassPointer();
2711 if (ecl && (fClass!=ecl )) {
2712 insp.InspectMember(ecl, eaddr, TString(element->GetName()) +
".", isTransient);
2722 element = (TStreamerElement*) next();
2723 for (; element; element = (TStreamerElement*) next()) {
2724 if (element->IsBase()) {
2726 if (element->GetOffset() == kMissing) {
2730 char* eaddr = ((
char*)obj) + element->GetOffset();
2732 TClass *ecl = element->GetClassPointer();
2734 ecl->CallShowMembers(eaddr, insp, isTransient);
2744 TObject *TStreamerInfo::Clone(
const char *newname)
const
2746 TStreamerInfo *newinfo = (TStreamerInfo*)TNamed::Clone(newname);
2747 if (newname && newname[0] && fName != newname) {
2748 TObjArray *newelems = newinfo->GetElements();
2749 Int_t ndata = newelems->GetEntries();
2750 for(Int_t i = 0; i < ndata; ++i) {
2751 TObject *element = newelems->UncheckedAt(i);
2752 if (element->IsA() == TStreamerLoop::Class()) {
2753 TStreamerLoop *eloop = (TStreamerLoop*)element;
2754 if (fName == eloop->GetCountClass()) {
2755 eloop->SetCountClass(newname);
2758 }
else if (element->IsA() == TStreamerBasicPointer::Class()) {
2759 TStreamerBasicPointer *eptr = (TStreamerBasicPointer*)element;
2760 if (fName == eptr->GetCountClass()) {
2761 eptr->SetCountClass(newname);
2768 newinfo->fNumber = fgCount;
2780 Bool_t TStreamerInfo::CompareContent(TClass *cl, TVirtualStreamerInfo *info, Bool_t warn, Bool_t complete, TFile *file)
2782 Bool_t result = kTRUE;
2783 R__ASSERT( (cl==0 || info==0) && (cl!=0 || info!=0) );
2787 TStreamerElement *el;
2788 TStreamerElement *infoel = 0;
2790 TIter next(GetElements());
2791 TIter infonext((TList*)0);
2792 TIter basenext((TList*)0);
2793 TIter membernext((TList*)0);
2795 infonext = info->GetElements();
2798 TList *tlb = cl->GetListOfBases();
2802 tlb = cl->GetListOfDataMembers();
2809 Bool_t done = kFALSE;
2815 el = (TStreamerElement*)next();
2816 if (el && el->IsBase()) {
2817 localClass = el->GetName();
2822 TBaseClass *tbc = (TBaseClass*)basenext();
2824 otherClass = tbc->GetName();
2830 infoel = (TStreamerElement*)infonext();
2831 if (infoel && infoel->IsBase()) {
2832 otherClass = infoel->GetName();
2838 if (TClassEdit::IsSTLCont(localClass)) {
2839 localClass = TClassEdit::ShortType( localClass, TClassEdit::kDropStlDefault );
2840 otherClass = TClassEdit::ShortType( otherClass, TClassEdit::kDropStlDefault );
2843 if (localClass != otherClass) {
2846 Warning(
"CompareContent",
2847 "The in-memory layout version %d for class '%s' has a base class (%s) that the on-file layout version %d does not have.",
2848 GetClassVersion(), GetName(), otherClass.Data(), GetClassVersion());
2849 }
else if (otherClass.Length()==0) {
2850 Warning(
"CompareContent",
2851 "The on-file layout version %d for class '%s' has a base class (%s) that the in-memory layout version %d does not have",
2852 GetClassVersion(), GetName(), localClass.Data(), GetClassVersion());
2854 Warning(
"CompareContent",
2855 "One base class of the on-file layout version %d and of the in memory layout version %d for '%s' is different: '%s' vs '%s'",
2856 GetClassVersion(), GetClassVersion(), GetName(), localClass.Data(), otherClass.Data());
2859 if (!complete)
return kFALSE;
2860 result = result && kFALSE;
2863 TStreamerBase *localBase =
dynamic_cast<TStreamerBase*
>(el);
2864 if (!localBase)
continue;
2866 TClass *otherBaseClass = localBase->GetClassPointer();
2867 if (!otherBaseClass)
continue;
2868 if (otherBaseClass->IsVersioned() && localBase->GetBaseVersion() != otherBaseClass->GetClassVersion()) {
2870 msg.Form(
" The StreamerInfo of class %s read from %s%s\n"
2871 " has the same version (=%d) as the active class but a different checksum.\n"
2872 " You should update the version to ClassDef(%s,%d).\n"
2873 " The objects on this file might not be readable because:\n"
2874 " The in-memory layout version %d for class '%s' has a base class (%s) with version %d but the on-file layout version %d recorded the version number %d for this base class (%s).",
2875 GetName(), file ?
"file " :
"", file ? file->GetName() :
"", fClassVersion, GetName(), fClassVersion + 1,
2876 GetClassVersion(), GetName(), otherClass.Data(), otherBaseClass->GetClassVersion(),
2877 GetClassVersion(), localBase->GetBaseVersion(), localClass.Data());
2878 TStreamerBase *otherBase = (TStreamerBase*)cl->GetStreamerInfo()->GetElements()->FindObject(otherClass);
2879 otherBase->SetErrorMessage(msg);
2881 }
else if (!otherBaseClass->IsVersioned() && localBase->GetBaseCheckSum() != otherBaseClass->GetCheckSum()) {
2882 TVirtualStreamerInfo *localBaseInfo = otherBaseClass->FindStreamerInfo(localBase->GetBaseCheckSum());
2883 if (!localBaseInfo) {
2887 const TList *list = file->GetStreamerInfoCache();
2888 localBaseInfo = list ? (TStreamerInfo*)list->FindObject(localBase->GetName()) : 0;
2890 if (!localBaseInfo) {
2892 msg.Form(
" The StreamerInfo of the base class %s (of class %s) read from %s%s\n"
2893 " refers to a checksum (%x) that can not be found neither in memory nor in the file.\n",
2894 otherBaseClass->GetName(), localClass.Data(),
2895 file ?
"file " :
"", file ? file->GetName() :
"",
2896 localBase->GetBaseCheckSum()
2898 TStreamerBase *otherBase = (TStreamerBase*)cl->GetStreamerInfo()->GetElements()->FindObject(otherClass);
2899 otherBase->SetErrorMessage(msg);
2902 if (localBaseInfo->CompareContent(otherBaseClass,0,kFALSE,kFALSE,file) ) {
2907 msg.Form(
" The StreamerInfo of class %s read from %s%s\n"
2908 " has the same version (=%d) as the active class but a different checksum.\n"
2909 " You should update the version to ClassDef(%s,%d).\n"
2910 " The objects on this file might not be readable because:\n"
2911 " The in-memory layout version %d for class '%s' has a base class (%s) with checksum %x but the on-file layout version %d recorded the checksum value %x for this base class (%s).",
2912 GetName(), file ?
"file " :
"", file ? file->GetName() :
"", fClassVersion, GetName(), fClassVersion + 1,
2913 GetClassVersion(), GetName(), otherClass.Data(), otherBaseClass->GetCheckSum(),
2914 GetClassVersion(), localBase->GetBaseCheckSum(), localClass.Data());
2915 TStreamerBase *otherBase = (TStreamerBase*)cl->GetStreamerInfo()->GetElements()->FindObject(otherClass);
2916 otherBase->SetErrorMessage(msg);
2919 TStreamerBase *localBase =
dynamic_cast<TStreamerBase*
>(el);
2920 TStreamerBase *otherBase =
dynamic_cast<TStreamerBase*
>(infoel);
2921 if (!localBase || !otherBase)
continue;
2924 TClass *otherBaseClass = localBase->GetClassPointer();
2925 if (otherBaseClass->IsVersioned() && localBase->GetBaseVersion() != otherBase->GetBaseVersion()) {
2927 msg.Form(
" The StreamerInfo of class %s read from %s%s\n"
2928 " has the same version (=%d) as the active class but a different checksum.\n"
2929 " You should update the version to ClassDef(%s,%d).\n"
2930 " The objects on this file might not be readable because:\n"
2931 " The in-memory layout version %d for class '%s' has a base class (%s) with version %d but the on-file layout version %d recorded the version number %d for this base class (%s).",
2932 GetName(), file ?
"file " :
"", file ? file->GetName() :
"", fClassVersion, GetName(), fClassVersion + 1,
2933 GetClassVersion(), GetName(), otherClass.Data(), otherBase->GetBaseVersion(),
2934 GetClassVersion(), localBase->GetBaseVersion(), localClass.Data());
2935 otherBase->SetErrorMessage(msg);
2937 }
else if (!otherBaseClass->IsVersioned() && localBase->GetBaseCheckSum() != otherBase->GetBaseCheckSum())
2939 TVirtualStreamerInfo *localBaseInfo = otherBaseClass->FindStreamerInfo(localBase->GetBaseCheckSum());
2940 TVirtualStreamerInfo *otherBaseInfo = otherBaseClass->FindStreamerInfo(otherBase->GetBaseCheckSum());
2941 if (localBaseInfo == otherBaseInfo ||
2942 localBaseInfo->CompareContent(0,otherBaseInfo,kFALSE,kFALSE,file) ) {
2947 msg.Form(
" The StreamerInfo of class %s read from %s%s\n"
2948 " has the same version (=%d) as the active class but a different checksum.\n"
2949 " You should update the version to ClassDef(%s,%d).\n"
2950 " The objects on this file might not be readable because:\n"
2951 " The in-memory layout version %d for class '%s' has a base class (%s) with checksum %x but the on-file layout version %d recorded the checksum value %x for this base class (%s).",
2952 GetName(), file ?
"file " :
"", file ? file->GetName() :
"", fClassVersion, GetName(), fClassVersion + 1,
2953 GetClassVersion(), GetName(), otherClass.Data(), otherBase->GetBaseCheckSum(),
2954 GetClassVersion(), localBase->GetBaseCheckSum(), localClass.Data());
2955 otherBase->SetErrorMessage(msg);
2959 if (!result && !complete) {
2967 TMemberInfo local(GetClass());
2968 TMemberInfo other(cl ? cl : info->GetClass());
2973 el = (TStreamerElement*)next();
2974 while (el && (el->IsBase() || el->IsA() == TStreamerArtificial::Class())) {
2975 el = (TStreamerElement*)next();
2979 local.SetName( el->GetName() );
2980 local.SetClassName( el->GetTypeName() );
2981 local.SetComment( el->GetTitle() );
2982 local.SetDataType( el->GetType() );
2985 TDataMember *tdm = (TDataMember*)membernext();
2986 while(tdm && ( (!tdm->IsPersistent()) || (tdm->Property()&kIsStatic) || (el && local.fName != tdm->GetName()) )) {
2987 tdm = (TDataMember*)membernext();
2990 other.SetName( tdm->GetName() );
2991 other.SetClassName( tdm->GetTrueTypeName() );
2992 other.SetComment( tdm->GetTitle() );
2993 if (tdm->GetDataType()) {
2995 if (tdm->IsaPointer()) {
2996 if (tdm->GetDataType()->GetType() == TVirtualStreamerInfo::kChar && !tdm->GetArrayDim() && tdm->GetArrayIndex()[0]==0) {
2997 other.SetDataType( TVirtualStreamerInfo::kCharStar );
2999 other.SetDataType( tdm->GetDataType()->GetType() + TVirtualStreamerInfo::kOffsetP);
3002 if (tdm->GetArrayDim()) {
3003 other.SetDataType( tdm->GetDataType()->GetType() + TVirtualStreamerInfo::kOffsetL);
3005 other.SetDataType( tdm->GetDataType()->GetType() );
3014 infoel = (TStreamerElement*)infonext();
3015 while (infoel && (infoel->IsBase() || infoel->IsA() == TStreamerArtificial::Class())) {
3016 infoel = (TStreamerElement*)infonext();
3019 other.SetName( infoel->GetName() );
3020 other.SetClassName( infoel->GetTypeName() );
3021 other.SetComment( infoel->GetTitle() );
3022 other.SetDataType( infoel->GetType() );
3031 Warning(
"CompareContent",
"The following data member of\nthe in-memory layout version %d of class '%s' is missing from \nthe on-file layout version %d:\n"
3033 ,GetClassVersion(), GetName(), GetClassVersion()
3034 ,other.fClassName.Data(),other.fName.Data(),other.fComment.Data());
3036 }
else if (other.fName.Length()==0) {
3037 Warning(
"CompareContent",
"The following data member of\nthe in-memory layout version %d of class '%s' is missing from \nthe on-file layout version %d:\n"
3039 ,GetClassVersion(), GetName(), GetClassVersion()
3040 ,local.fClassName.Data(),local.fName.Data(),local.fComment.Data());
3042 Warning(
"CompareContent",
"The following data member of\nthe on-file layout version %d of class '%s' differs from \nthe in-memory layout version %d:\n"
3046 ,GetClassVersion(), GetName(), GetClassVersion()
3047 ,local.fClassName.Data(),local.fName.Data(),local.fComment.Data()
3048 ,other.fClassName.Data(),other.fName.Data(),other.fComment.Data());
3051 result = result && kFALSE;
3052 if (!complete)
return result;
3063 void TStreamerInfo::ComputeSize()
3065 TStreamerElement *element = (TStreamerElement*)fElements->Last();
3068 fSize = element ? element->GetOffset() + element->GetSize() : 0;
3069 if (fNVirtualInfoLoc > 0 && (fVirtualInfoLoc[0]+
sizeof(TStreamerInfo*)) >= (ULong_t)fSize) {
3070 fSize = fVirtualInfoLoc[0] +
sizeof(TStreamerInfo*);
3076 constexpr
size_t kSizeOfPtr =
sizeof(
void*);
3077 if ((fSize % kSizeOfPtr) != 0) {
3078 fSize = fSize - (fSize % kSizeOfPtr) + kSizeOfPtr;
3094 void TStreamerInfo::ForceWriteInfo(TFile* file, Bool_t force)
3096 if (!file || fNumber < 0) {
3100 TArrayC* cindex = file->GetClassIndex();
3107 (cindex->fArray[fNumber] && !force) ||
3108 (cindex->fArray[fNumber] > 1)
3114 static TClassRef string_classref(
"string");
3115 if (fClass == string_classref) {
3123 if (fElements && fElements->GetEntries()==1 && strcmp(
"This",fElements->UncheckedAt(0)->GetName())==0) {
3127 }
else if (fClass->GetCollectionProxy()) {
3132 cindex->fArray[fNumber] = 2;
3134 cindex->fArray[0] = 1;
3137 TIter next(fElements);
3138 TStreamerElement* element = (TStreamerElement*) next();
3139 for (; element; element = (TStreamerElement*) next()) {
3140 if (element->IsTransient())
continue;
3141 TClass* cl = element->GetClassPointer();
3143 TVirtualStreamerInfo* si = 0;
3144 if (cl->Property() & kIsAbstract) {
3149 si = cl->GetCurrentStreamerInfo();
3151 si = cl->GetStreamerInfo();
3154 si->ForceWriteInfo(file, force);
3168 TClass *TStreamerInfo::GetActualClass(
const void *obj)
const
3170 R__ASSERT(!fClass->IsLoaded());
3172 if (fNVirtualInfoLoc != 0) {
3173 TStreamerInfo *allocator = *(TStreamerInfo**)( (
const char*)obj + fVirtualInfoLoc[0] );
3174 if (allocator)
return allocator->GetClass();
3176 return (TClass*)fClass;
3183 Bool_t TStreamerInfo::MatchLegacyCheckSum(UInt_t checksum)
const
3185 for(UInt_t i = 1; i < TClass::kLatestCheckSum; ++i) {
3186 if ( checksum == GetCheckSum( (TClass::ECheckSum) i) )
return kTRUE;
3211 UInt_t TStreamerInfo::GetCheckSum(TClass::ECheckSum code)
const
3216 if (code == TClass::kCurrentCheckSum) code = TClass::kLatestCheckSum;
3221 TString name = GetName();
3224 for (
int i=0; i<il; i++)
id =
id*3+name[i];
3226 TIter next(GetElements());
3227 TStreamerElement *el;
3231 if (!fClass->GetCollectionProxy() && strncmp(fClass->GetName(),
"pair<", 5)) {
3232 while ( (el=(TStreamerElement*)next())) {
3234 name = el->GetName();
3236 for (
int i=0; i<il; i++)
id =
id*3+name[i];
3237 if (code > TClass::kNoBaseCheckSum && el->IsA() == TStreamerBase::Class()) {
3238 TStreamerBase *base = (TStreamerBase*)el;
3239 id =
id*3 + base->GetBaseCheckSum();
3246 while ( (el=(TStreamerElement*)next()) ) {
3247 if (el->IsBase())
continue;
3251 Bool_t isenum = kFALSE;
3252 if ( el->GetType()==3 && gROOT->GetType(el->GetTypeName())==0) {
3257 if ( (code > TClass::kNoEnum) && isenum)
id =
id*3 + 1;
3259 name = el->GetName(); il = name.Length();
3262 for (i=0; i<il; i++)
id =
id*3+name[i];
3264 if (code == TClass::kReflex || code == TClass::kReflexNoComment) {
3267 type = TClassEdit::ResolveTypedef(el->GetTypeName(),kTRUE);
3269 }
else if (code <= TClass::kWithTypeDef) {
3276 type = el->GetTypeName();
3278 type = TClassEdit::GetLong64_Name(TClassEdit::ResolveTypedef(el->GetTypeName(),kTRUE));
3280 if (TClassEdit::IsSTLCont(type)) {
3281 type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault | TClassEdit::kLong64 );
3283 if (code == TClass::kReflex || code == TClass::kReflexNoComment) {
3284 type.ReplaceAll(
"ULong64_t",
"unsigned long long");
3285 type.ReplaceAll(
"Long64_t",
"long long");
3286 type.ReplaceAll(
"signed char",
"char");
3287 type.ReplaceAll(
"<signed char",
"<char");
3288 type.ReplaceAll(
",signed char",
",char");
3289 if (type==
"signed char") type =
"char";
3293 for (i=0; i<il; i++)
id =
id*3+type[i];
3295 int dim = el->GetArrayDim();
3297 for (i=0;i<dim;i++)
id =
id*3+el->GetMaxIndex(i);
3301 if (code > TClass::kNoRange) {
3303 if (code > TClass::kNoRangeCheck)
3304 left = TVirtualStreamerInfo::GetElementCounterStart(el->GetTitle());
3306 left = strstr(el->GetTitle(),
"[");
3308 const char *right = strstr(left,
"]");
3311 while (left != right) {
3324 static void R__WriteConstructorBody(FILE *file, TIter &next)
3326 TStreamerElement *element = 0;
3328 while ((element = (TStreamerElement*)next())) {
3329 if (element->GetType() == TVirtualStreamerInfo::kObjectp || element->GetType() == TVirtualStreamerInfo::kObjectP ||
3330 element->GetType() == TVirtualStreamerInfo::kAnyp || element->GetType() == TVirtualStreamerInfo::kAnyP ||
3331 element->GetType() == TVirtualStreamerInfo::kCharStar || element->GetType() == TVirtualStreamerInfo::kSTLp ||
3332 element->GetType() == TVirtualStreamerInfo::kStreamLoop) {
3333 if(element->GetArrayLength() <= 1) {
3334 fprintf(file,
" %s = 0;\n",element->GetName());
3336 fprintf(file,
" memset(%s,0,%d);\n",element->GetName(),element->GetSize());
3339 if (TVirtualStreamerInfo::kOffsetP <= element->GetType() && element->GetType() < TVirtualStreamerInfo::kObject ) {
3340 fprintf(file,
" %s = 0;\n",element->GetName());
3345 static constexpr
int str_length(
const char* str)
3347 return *str ? 1 + str_length(str + 1) : 0;
3353 static bool R__IsUniquePtr(TStreamerElement *element) {
3355 constexpr
auto auto_ptr_len = str_length(
"auto_ptr<");
3356 constexpr
auto unique_ptr_len = str_length(
"unique_ptr<");
3358 const char *name = element->GetTypeNameBasic();
3360 return ((strncmp(name,
"auto_ptr<", auto_ptr_len) == 0)
3361 || (strncmp(name,
"unique_ptr<", unique_ptr_len) == 0));
3367 static void R__WriteMoveConstructorBody(FILE *file,
const TString &protoname, TIter &next)
3369 TStreamerElement *element = 0;
3371 Bool_t atstart = kTRUE;
3372 while ((element = (TStreamerElement*)next())) {
3373 if (element->IsBase()) {
3374 if (atstart) { fprintf(file,
" : "); atstart = kFALSE; }
3375 else fprintf(file,
" , ");
3376 fprintf(file,
"%s(const_cast<%s &>( rhs ))\n", element->GetName(),protoname.Data());
3378 if (element->GetArrayLength() <= 1) {
3379 if (atstart) { fprintf(file,
" : "); atstart = kFALSE; }
3380 else fprintf(file,
" , ");
3381 if (R__IsUniquePtr(element)) {
3382 fprintf(file,
"%s(const_cast<%s &>( rhs ).%s.release() )\n",element->GetName(),protoname.Data(),element->GetName());
3384 fprintf(file,
"%s(const_cast<%s &>( rhs ).%s)\n",element->GetName(),protoname.Data(),element->GetName());
3389 fprintf(file,
"{\n");
3390 fprintf(file,
" // This is NOT a copy constructor. This is actually a move constructor (for stl container's sake).\n");
3391 fprintf(file,
" // Use at your own risk!\n");
3392 fprintf(file,
" (void)rhs; // avoid warning about unused parameter\n");
3394 Bool_t defMod = kFALSE;
3395 while ((element = (TStreamerElement*)next())) {
3396 if (element->GetType() == TVirtualStreamerInfo::kObjectp || element->GetType() == TVirtualStreamerInfo::kObjectP||
3397 element->GetType() == TVirtualStreamerInfo::kAnyp || element->GetType() == TVirtualStreamerInfo::kAnyP
3398 || element->GetType() == TVirtualStreamerInfo::kAnyPnoVT)
3400 if (!defMod) { fprintf(file,
" %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE; };
3401 const char *ename = element->GetName();
3402 const char *colon2 = strstr(ename,
"::");
3403 if (colon2) ename = colon2+2;
3404 if(element->GetArrayLength() <= 1) {
3405 fprintf(file,
" modrhs.%s = 0;\n",ename);
3407 fprintf(file,
" memset(modrhs.%s,0,%d);\n",ename,element->GetSize());
3410 const char *ename = element->GetName();
3411 if (element->GetType() == kCharStar) {
3413 fprintf(file,
" %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE;
3415 fprintf(file,
" modrhs.%s = 0;\n",ename);
3416 }
else if (TVirtualStreamerInfo::kOffsetP <= element->GetType() && element->GetType() < TVirtualStreamerInfo::kObject ) {
3418 fprintf(file,
" %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE;
3420 fprintf(file,
" modrhs.%s = 0;\n",ename);
3421 }
else if (element->GetArrayLength() > 1) {
3423 if (element->GetArrayDim() == 1) {
3424 fprintf(file,
" for (Int_t i=0;i<%d;i++) %s[i] = rhs.%s[i];\n",element->GetArrayLength(),ename,ename);
3425 }
else if (element->GetArrayDim() >= 2) {
3426 fprintf(file,
" for (Int_t i=0;i<%d;i++) (&(%s",element->GetArrayLength(),ename);
3427 for (Int_t d = 0; d < element->GetArrayDim(); ++d) {
3428 fprintf(file,
"[0]");
3430 fprintf(file,
"))[i] = (&(rhs.%s",ename);
3431 for (Int_t d = 0; d < element->GetArrayDim(); ++d) {
3432 fprintf(file,
"[0]");
3434 fprintf(file,
"))[i];\n");
3436 }
else if (element->GetType() == TVirtualStreamerInfo::kSTLp) {
3437 if (!defMod) { fprintf(file,
" %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE; };
3438 fprintf(file,
" modrhs.%s = 0;\n",ename);
3439 }
else if (element->GetType() == TVirtualStreamerInfo::kSTL) {
3441 fprintf(file,
" %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE;
3443 TClass *cle = element->GetClassPointer();
3444 TVirtualCollectionProxy *proxy = cle ? element->GetClassPointer()->GetCollectionProxy() : 0;
3445 std::string method_name =
"clear";
3446 if (!element->TestBit(TStreamerElement::kDoNotDelete) && proxy && (((TStreamerSTL*)element)->GetSTLtype() == ROOT::kSTLbitset)) {
3447 method_name =
"reset";
3449 if (element->IsBase()) {
3450 fprintf(file,
" modrhs.%s();\n", method_name.c_str());
3452 fprintf(file,
" modrhs.%s.%s();\n",ename, method_name.c_str());
3461 static void R__WriteDestructorBody(FILE *file, TIter &next)
3463 TStreamerElement *element = 0;
3465 while ((element = (TStreamerElement*)next())) {
3466 if (element->GetType() == TVirtualStreamerInfo::kObjectp || element->GetType() == TVirtualStreamerInfo::kObjectP||
3467 element->GetType() == TVirtualStreamerInfo::kAnyp || element->GetType() == TVirtualStreamerInfo::kAnyP
3468 || element->GetType() == TVirtualStreamerInfo::kAnyPnoVT)
3470 const char *ename = element->GetName();
3471 const char *colon2 = strstr(ename,
"::");
3472 if (colon2) ename = colon2+2;
3473 if (element->TestBit(TStreamerElement::kDoNotDelete)) {
3474 if(element->GetArrayLength() <= 1) {
3475 fprintf(file,
" %s = 0;\n",ename);
3477 fprintf(file,
" memset(%s,0,%d);\n",ename,element->GetSize());
3480 if(element->GetArrayLength() <= 1) {
3481 fprintf(file,
" delete %s; %s = 0;\n",ename,ename);
3483 fprintf(file,
" for (Int_t i=0;i<%d;i++) delete %s[i]; memset(%s,0,%d);\n",element->GetArrayLength(),ename,ename,element->GetSize());
3487 if (element->GetType() == TVirtualStreamerInfo::kCharStar) {
3488 const char *ename = element->GetName();
3489 if (element->TestBit(TStreamerElement::kDoNotDelete)) {
3490 fprintf(file,
" %s = 0;\n",ename);
3492 fprintf(file,
" delete [] %s; %s = 0;\n",ename,ename);
3495 if (TVirtualStreamerInfo::kOffsetP <= element->GetType() && element->GetType() < TVirtualStreamerInfo::kObject ) {
3496 const char *ename = element->GetName();
3497 if (element->TestBit(TStreamerElement::kDoNotDelete)) {
3498 fprintf(file,
" %s = 0;\n",ename);
3499 }
else if (element->HasCounter()) {
3500 fprintf(file,
" delete %s; %s = 0;\n",ename,ename);
3502 fprintf(file,
" delete [] %s; %s = 0;\n",ename,ename);
3505 if (element->GetType() == TVirtualStreamerInfo::kSTL || element->GetType() == TVirtualStreamerInfo::kSTLp) {
3506 const char *ename = element->GetName();
3507 const char *prefix =
"";
3508 if ( element->GetType() == TVirtualStreamerInfo::kSTLp ) {
3510 }
else if ( element->IsBase() ) {
3513 TClass *cle = element->GetClassPointer();
3514 TVirtualCollectionProxy *proxy = cle ? element->GetClassPointer()->GetCollectionProxy() : 0;
3515 if (!element->TestBit(TStreamerElement::kDoNotDelete) && proxy) {
3516 Int_t stltype = ((TStreamerSTL*)element)->GetSTLtype();
3518 if (proxy->HasPointers()) {
3519 fprintf(file,
" std::for_each( (%s %s).rbegin(), (%s %s).rend(), DeleteObjectFunctor() );\n",prefix,ename,prefix,ename);
3525 if (stltype == ROOT::kSTLmap || stltype == ROOT::kSTLmultimap) {
3526 TString enamebasic = TMakeProject::UpdateAssociativeToVector(element->GetTypeNameBasic());
3527 std::vector<std::string> inside;
3529 TClassEdit::GetSplit(enamebasic, inside, nestedLoc, TClassEdit::kLong64);
3530 if (inside[1][inside[1].size()-1]==
'*' || inside[2][inside[2].size()-1]==
'*') {
3531 fprintf(file,
" std::for_each( (%s %s).rbegin(), (%s %s).rend(), DeleteObjectFunctor() );\n",prefix,ename,prefix,ename);
3537 fprintf(file,
" delete %s; %s = 0;\n",ename,ename);
3546 void TStreamerInfo::GenerateDeclaration(FILE *fp, FILE *sfp,
const TList *subClasses, Bool_t top)
3548 if (fClassVersion == -3) {
3552 Bool_t needGenericTemplate = fElements==0 || fElements->GetEntries() == 0;
3553 Bool_t isTemplate = kFALSE;
3554 const char *clname = GetName();
3555 TString template_protoname;
3556 if (strchr(clname,
':')) {
3558 Int_t len = strlen(clname);
3559 const char *name = clname;
3562 for (Int_t cur = 0; cur < len; ++cur) {
3563 switch (clname[cur]) {
3570 if (nest == 0) { cur = len;
continue; }
3574 if (nest == 0 && clname[cur+1] ==
':') {
3576 isTemplate = kFALSE;
3577 name = clname + cur + 2;
3584 template_protoname.Append(clname,pr_pos);
3588 const char *where = strstr(clname,
"<");
3589 isTemplate = where != 0;
3591 template_protoname.Append(clname,where-clname);
3595 if (needGenericTemplate && isTemplate) {
3596 TString templateName(TMakeProject::GetHeaderName(
"template "+template_protoname,0));
3597 fprintf(fp,
"#ifndef %s_h\n", templateName.Data());
3598 fprintf(fp,
"#define %s_h\n", templateName.Data());
3602 UInt_t numberOfNamespaces = TMakeProject::GenerateClassPrefix(fp, GetName(), top, protoname, 0, kFALSE, needGenericTemplate);
3605 TStreamerElement *element;
3606 TIter next(fElements);
3608 while ((element = (TStreamerElement*)next())) {
3609 if (!element->IsBase())
continue;
3611 const char *ename = element->GetName();
3612 if (nbase == 1) fprintf(fp,
" : public %s",ename);
3613 else fprintf(fp,
" , public %s",ename);
3618 if (subClasses && subClasses->GetEntries()) {
3619 Bool_t needheader =
true;
3621 TIter subnext(subClasses);
3622 TStreamerInfo *subinfo;
3623 Int_t len = strlen(GetName());
3624 while ((subinfo = (TStreamerInfo*)subnext())) {
3625 if (strncmp(GetName(),subinfo->GetName(),len)==0 && (subinfo->GetName()[len]==
':') ) {
3626 if (subinfo->GetName()[len+1]==
':' && strstr(subinfo->GetName()+len+2,
":")==0) {
3628 fprintf(fp,
"\npublic:\n");
3629 fprintf(fp,
"// Nested classes forward declaration.\n");
3632 TString sub_protoname;
3633 UInt_t sub_numberOfClasses = 0;
3634 UInt_t sub_numberOfNamespaces;
3635 if (subinfo->GetClassVersion() == -3) {
3636 sub_numberOfNamespaces = TMakeProject::GenerateClassPrefix(fp, subinfo->GetName() + len+2, kFALSE, sub_protoname, &sub_numberOfClasses, 3);
3638 sub_numberOfNamespaces = TMakeProject::GenerateClassPrefix(fp, subinfo->GetName() + len+2, kFALSE, sub_protoname, &sub_numberOfClasses, kFALSE);
3642 for (UInt_t i = 0;i < sub_numberOfClasses;++i) {
3643 fprintf(fp,
"}; // end of class.\n");
3645 if (sub_numberOfNamespaces > 0) {
3646 Error(
"GenerateDeclaration",
"Nested classes %s thought to be inside a namespace inside the class %s",subinfo->GetName(),GetName());
3653 fprintf(fp,
"\npublic:\n");
3654 fprintf(fp,
"// Nested classes declaration.\n");
3657 if (subClasses && subClasses->GetEntries()) {
3658 TIter subnext(subClasses,kIterBackward);
3659 TStreamerInfo *subinfo;
3660 Int_t len = strlen(GetName());
3661 while ((subinfo = (TStreamerInfo*)subnext())) {
3662 if (strncmp(GetName(),subinfo->GetName(),len)==0 && (subinfo->GetName()[len]==
':')) {
3663 if (subinfo->GetName()[len+1]==
':' && strstr(subinfo->GetName()+len+2,
":")==0) {
3664 subinfo->GenerateDeclaration(fp, sfp, subClasses, kFALSE);
3670 fprintf(fp,
"\npublic:\n");
3671 fprintf(fp,
"// Data Members.\n");
3680 line.Resize(kMaxLen);
3682 while ((element = (TStreamerElement*)next())) {
3684 if (element->IsBase())
continue;
3685 const char *ename = element->GetName();
3688 for (Int_t i=0;i < element->GetArrayDim();i++) {
3689 name += TString::Format(
"[%d]",element->GetMaxIndex(i));
3694 TString enamebasic = element->GetTypeNameBasic();
3695 if (element->IsA() == TStreamerSTL::Class()) {
3700 Int_t stltype = ((TStreamerSTL*)element)->GetSTLtype();
3703 case ROOT::kSTLmultimap:
3705 case ROOT::kSTLmultiset:
3706 case ROOT::kSTLunorderedset:
3707 case ROOT::kSTLunorderedmultiset:
3709 enamebasic = TMakeProject::UpdateAssociativeToVector(enamebasic);
3715 }
else if (strncmp(enamebasic.Data(),
"auto_ptr<", strlen(
"auto_ptr<")) == 0) {
3716 enamebasic = TMakeProject::UpdateAssociativeToVector(enamebasic);
3719 lt = enamebasic.Length();
3723 if (lt>=ltype) ltype = lt+1;
3725 for (is = 3+lt; is < (3+ltype); ++is) line +=
' ';
3728 if (element->IsaPointer() && !strchr(line,
'*')) line[2+ltype] =
'*';
3730 if (ld>=ldata) ldata = ld+1;
3731 for (is = 3+ltype+ld; is < (3+ltype+ldata); ++is) line +=
' ';
3734 line += element->GetTitle();
3735 fprintf(fp,
"%s\n",line.Data());
3738 if (needGenericTemplate && isTemplate) {
3740 fprintf(fp,
"\n %s() {\n",protoname.Data());
3741 R__WriteConstructorBody(fp,next);
3743 fprintf(fp,
" %s(%s && ) = default;\n",protoname.Data(),protoname.Data());
3744 fprintf(fp,
" %s(const %s & rhs )\n",protoname.Data(),protoname.Data());
3745 R__WriteMoveConstructorBody(fp,protoname,next);
3747 fprintf(fp,
" virtual ~%s() {\n",protoname.Data());
3748 R__WriteDestructorBody(fp,next);
3749 fprintf(fp,
" }\n\n");
3753 fprintf(fp,
"\n %s();\n",protoname.Data());
3754 fprintf(fp,
" %s(%s && ) = default;\n",protoname.Data(),protoname.Data());
3755 fprintf(fp,
" %s(const %s & );\n",protoname.Data(),protoname.Data());
3756 fprintf(fp,
" virtual ~%s();\n\n",protoname.Data());
3759 TString guard( TMakeProject::GetHeaderName( GetName(), 0, kTRUE ) );
3760 fprintf(sfp,
"#ifndef %s_cxx\n",guard.Data());
3761 fprintf(sfp,
"#define %s_cxx\n",guard.Data());
3762 fprintf(sfp,
"%s::%s() {\n",GetName(),protoname.Data());
3763 R__WriteConstructorBody(sfp,next);
3766 fprintf(sfp,
"%s::%s(const %s & rhs)\n",GetName(),protoname.Data(),protoname.Data());
3767 R__WriteMoveConstructorBody(sfp,protoname,next);
3770 fprintf(sfp,
"%s::~%s() {\n",GetName(),protoname.Data());
3771 R__WriteDestructorBody(sfp,next);
3773 fprintf(sfp,
"#endif // %s_cxx\n\n",guard.Data());
3776 TClass *cl = gROOT->GetClass(GetName());
3777 if (fClassVersion > 1 || (cl && cl->IsTObject()) ) {
3779 if (fClassVersion == 0) {
3781 fprintf(fp,
" ClassDef(%s,%d); // Generated by MakeProject.\n",protoname.Data(),0);
3783 fprintf(fp,
" ClassDef(%s,%d); // Generated by MakeProject.\n",protoname.Data(),fClassVersion + 1);
3788 for(UInt_t i=0;i<numberOfNamespaces;++i) {
3789 fprintf(fp,
"} // namespace\n");
3792 if (needGenericTemplate && isTemplate) {
3793 fprintf(fp,
"#endif // generic template declaration\n");
3800 UInt_t TStreamerInfo::GenerateIncludes(FILE *fp,
char *inclist,
const TList *extrainfos)
3802 if (inclist[0]==0) {
3804 TMakeProject::AddInclude( fp,
"Rtypes.h", kFALSE, inclist);
3808 const char *clname = GetName();
3809 if (strchr(clname,
'<')) {
3811 ninc += TMakeProject::GenerateIncludeForTemplate(fp, clname, inclist, kFALSE, extrainfos);
3819 TIter next(fElements);
3820 TStreamerElement *element;
3821 Bool_t incRiostream = kFALSE;
3822 while ((element = (TStreamerElement*)next())) {
3824 const char *ename = element->GetName();
3825 const char *colon2 = strstr(ename,
"::");
3826 if (colon2) ename = colon2+2;
3828 for (Int_t i=0;i < element->GetArrayDim();i++) {
3829 name += TString::Format(
"[%d]",element->GetMaxIndex(i));
3832 lt = strlen(element->GetTypeName());
3833 if (ltype < lt) ltype = lt;
3834 if (ldata < ld) ldata = ld;
3837 if (!incRiostream && element->InheritsFrom(TStreamerSTL::Class())) {
3838 incRiostream = kTRUE;
3839 TMakeProject::AddInclude( fp,
"Riostream.h", kFALSE, inclist);
3843 const char *include = element->GetInclude();
3844 if (!include[0])
continue;
3846 Bool_t greater = (include[0]==
'<');
3849 if (strncmp(include,
"include/",8)==0) {
3852 if (strncmp(include,
"include\\",9)==0) {
3855 if (strncmp(element->GetTypeName(),
"pair<",strlen(
"pair<"))==0) {
3856 TMakeProject::AddInclude( fp,
"utility", kTRUE, inclist);
3857 }
else if (strncmp(element->GetTypeName(),
"auto_ptr<",strlen(
"auto_ptr<"))==0) {
3858 TMakeProject::AddInclude( fp,
"memory", kTRUE, inclist);
3860 TString incName( include, strlen(include)-1 );
3861 incName = TMakeProject::GetHeaderName(incName,extrainfos);
3862 TMakeProject::AddInclude( fp, incName.Data(), greater, inclist);
3865 if (strchr(element->GetTypeName(),
'<')) {
3867 ninc += TMakeProject::GenerateIncludeForTemplate(fp, element->GetTypeName(), inclist, kFALSE, extrainfos);
3877 Int_t TStreamerInfo::GenerateHeaderFile(
const char *dirname,
const TList *subClasses,
const TList *extrainfos)
3880 if ((fClass && fClass->GetCollectionType()) || TClassEdit::IsSTLCont(GetName()))
return 0;
3881 if (strncmp(GetName(),
"pair<",strlen(
"pair<"))==0)
return 0;
3882 if (strncmp(GetName(),
"auto_ptr<",strlen(
"auto_ptr<"))==0)
return 0;
3884 TClass *cl = TClass::GetClass(GetName());
3886 if (cl->HasInterpreterInfo())
return 0;
3888 Bool_t isTemplate = kFALSE;
3889 if (strchr(GetName(),
':')) {
3890 UInt_t len = strlen(GetName());
3893 for(UInt_t i=len; i>0; --i) {
3894 switch(GetName()[i]) {
3895 case '>': ++nest;
if (scope==0) { isTemplate = kTRUE; }
break;
3896 case '<': --nest;
break;
3898 if (nest==0 && GetName()[i-1]==
':') {
3900 TString nsname(GetName(), i-1);
3901 cl = gROOT->GetClass(nsname);
3902 if (cl && (cl->Size()!=0 || (cl->Size()==0 && !cl->HasInterpreterInfo() ))) {
3905 }
else if (cl == 0 && extrainfos != 0) {
3906 TStreamerInfo *clinfo = (TStreamerInfo*)extrainfos->FindObject(nsname);
3907 if (clinfo && clinfo->GetClassVersion() == -5) {
3918 Bool_t needGenericTemplate = isTemplate && (fElements==0 || fElements->GetEntries()==0);
3920 if (gDebug) printf(
"generating code for class %s\n",GetName());
3924 TString headername( TMakeProject::GetHeaderName( GetName(), extrainfos ) );
3926 filename.Form(
"%s/%s.h",dirname,headername.Data());
3928 FILE *fp = fopen(filename.Data(),
"w");
3930 Error(
"MakeProject",
"Cannot open output file:%s\n",filename.Data());
3934 filename.Form(
"%s/%sProjectHeaders.h",dirname,gSystem->BaseName(dirname));
3935 FILE *allfp = fopen(filename.Data(),
"a");
3937 Error(
"MakeProject",
"Cannot open output file:%s\n",filename.Data());
3941 fprintf(allfp,
"#include \"%s.h\"\n", headername.Data());
3944 char *inclist =
new char[50000];
3949 fprintf(fp,
"//////////////////////////////////////////////////////////\n");
3950 fprintf(fp,
"// This class has been generated by TFile::MakeProject\n");
3951 fprintf(fp,
"// (%s by ROOT version %s)\n",td.AsString(),gROOT->GetVersion());
3952 fprintf(fp,
"// from the StreamerInfo in file %s\n",gDirectory->GetFile()->GetName());
3953 fprintf(fp,
"//////////////////////////////////////////////////////////\n");
3956 fprintf(fp,
"#ifndef %s_h\n",headername.Data());
3957 fprintf(fp,
"#define %s_h\n",headername.Data());
3958 TMakeProject::GenerateForwardDeclaration(fp, GetName(), inclist, kFALSE, needGenericTemplate, extrainfos);
3962 ninc += GenerateIncludes(fp, inclist, extrainfos);
3964 TIter subnext(subClasses);
3965 TStreamerInfo *subinfo;
3966 while ((subinfo = (TStreamerInfo*)subnext())) {
3967 ninc = subinfo->GenerateIncludes(fp, inclist, extrainfos);
3972 TString sourcename; sourcename.Form(
"%s/%sProjectSource.cxx", dirname, gSystem->BaseName(dirname) );
3973 FILE *sfp = fopen( sourcename.Data(),
"a" );
3975 GenerateDeclaration(fp, sfp, subClasses);
3977 Error(
"GenerateHeaderFile",
"Could not open %s for appending",sourcename.Data());
3979 TMakeProject::GeneratePostDeclaration(fp,
this, inclist);
3981 fprintf(fp,
"#endif\n");
3985 if (sfp) fclose(sfp);
3993 Int_t TStreamerInfo::GetDataMemberOffset(TDataMember *dm, TMemberStreamer *&streamer)
const
3995 TIter nextr(fClass->GetListOfRealData());
3996 char dmbracket[256];
3997 snprintf(dmbracket,255,
"%s[",dm->GetName());
3998 Int_t offset = kMissing;
3999 if (!fClass->IsLoaded()) {
4003 if (! (dm->Property() & kIsStatic) ) {
4005 offset = dm->GetOffset();
4009 while ((rdm = (TRealData*)nextr())) {
4010 char *rdmc = (
char*)rdm->GetName();
4013 if (dm->IsaPointer() && rdmc[0] ==
'*') rdmc++;
4015 if (rdm->GetDataMember() != dm)
continue;
4016 if (strcmp(rdmc,dm->GetName()) == 0) {
4017 offset = rdm->GetThisOffset();
4018 streamer = rdm->GetStreamer();
4021 if (strcmp(rdm->GetName(),dm->GetName()) == 0) {
4022 if (rdm->IsObject()) {
4023 offset = rdm->GetThisOffset();
4024 streamer = rdm->GetStreamer();
4028 if (strstr(rdm->GetName(),dmbracket)) {
4029 offset = rdm->GetThisOffset();
4030 streamer = rdm->GetStreamer();
4040 Int_t TStreamerInfo::GetOffset(
const char *elementName)
const
4042 if (elementName == 0)
return 0;
4045 TStreamerElement *elem = (TStreamerElement*)fElements->FindObject(elementName);
4046 if (elem) offset = elem->GetOffset();
4054 Int_t TStreamerInfo::GetSize()
const
4063 Int_t TStreamerInfo::GetSizeElements()
const
4065 TIter next(fElements);
4066 TStreamerElement *element;
4068 while ((element = (TStreamerElement*)next())) {
4069 asize += element->GetSize();
4083 TStreamerElement* TStreamerInfo::GetStreamerElement(
const char* datamember, Int_t& offset)
const
4091 TStreamerElement* element = (TStreamerElement*) fElements->FindObject(datamember);
4093 offset = element->GetOffset();
4099 if (fClass->HasDataMemberInfo()) {
4101 TStreamerElement* base_element = 0;
4102 TBaseClass* base = 0;
4103 TClass* base_cl = 0;
4104 Int_t base_offset = 0;
4105 Int_t local_offset = 0;
4106 TIter nextb(fClass->GetListOfBases());
4108 while ((base = (TBaseClass*) nextb())) {
4109 base_cl = TClass::GetClass(base->GetName());
4110 base_element = (TStreamerElement*) fElements->FindObject(base->GetName());
4111 if (!base_cl || !base_element) {
4114 base_offset = base_element->GetOffset();
4115 element = ((TStreamerInfo*)base_cl->GetStreamerInfo())->GetStreamerElement(datamember, local_offset);
4117 offset = base_offset + local_offset;
4123 TIter next(fElements);
4124 TStreamerElement* curelem = 0;
4125 while ((curelem = (TStreamerElement*) next())) {
4126 if (curelem->InheritsFrom(TStreamerBase::Class())) {
4127 TClass* baseClass = curelem->GetClassPointer();
4131 Int_t base_offset = curelem->GetOffset();
4132 Int_t local_offset = 0;
4133 TStreamerInfo *baseInfo;
4134 if (baseClass->Property() & kIsAbstract) {
4135 baseInfo = (TStreamerInfo*)baseClass->GetStreamerInfoAbstractEmulated();
4137 baseInfo = (TStreamerInfo*)baseClass->GetStreamerInfo();
4139 if (baseInfo) element = baseInfo->GetStreamerElement(datamember, local_offset);
4141 offset = base_offset + local_offset;
4187 TStreamerElement* TStreamerInfo::GetStreamerElementReal(Int_t i, Int_t j)
const
4189 ::Obsolete(
"TStreamerInfo::GetStreamerElementReal",
"v5-34-20",
"v6-00-02");
4191 if (i < 0 || i >= fNdata)
return 0;
4192 if (j < 0)
return 0;
4193 if (!fElements)
return 0;
4194 TStreamerElement *se = (TStreamerElement*)fCompOpt[i]->fElem;
4196 Int_t nelems = fElements->GetEntriesFast();
4197 for (Int_t ise=0;ise < nelems;ise++) {
4198 if (se != (TStreamerElement*)fElements->UncheckedAt(ise))
continue;
4199 if (ise+j >= nelems)
return 0;
4200 return (TStreamerElement*)fElements->UncheckedAt(ise+j);
4208 template <
typename T>
4209 T TStreamerInfo::GetTypedValueAux(Int_t type,
void *ladd, Int_t k, Int_t len)
4211 if (type>=kConv && type<kSTL) {
4216 case kBool: {Bool_t *val = (Bool_t*)ladd;
return T(*val);}
4217 case kChar: {Char_t *val = (Char_t*)ladd;
return T(*val);}
4218 case kShort: {Short_t *val = (Short_t*)ladd;
return T(*val);}
4219 case kInt: {Int_t *val = (Int_t*)ladd;
return T(*val);}
4220 case kLong: {Long_t *val = (Long_t*)ladd;
return T(*val);}
4221 case kLong64: {Long64_t *val = (Long64_t*)ladd;
return T(*val);}
4222 case kFloat: {Float_t *val = (Float_t*)ladd;
return T(*val);}
4223 case kFloat16: {Float_t *val = (Float_t*)ladd;
return T(*val);}
4224 case kDouble: {Double_t *val = (Double_t*)ladd;
return T(*val);}
4225 case kDouble32: {Double_t *val = (Double_t*)ladd;
return T(*val);}
4226 case kUChar: {UChar_t *val = (UChar_t*)ladd;
return T(*val);}
4227 case kUShort: {UShort_t *val = (UShort_t*)ladd;
return T(*val);}
4228 case kUInt: {UInt_t *val = (UInt_t*)ladd;
return T(*val);}
4229 case kULong: {ULong_t *val = (ULong_t*)ladd;
return T(*val);}
4230 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
4231 case kULong64: {Long64_t *val = (Long64_t*)ladd;
return T(*val);}
4233 case kULong64: {ULong64_t *val= (ULong64_t*)ladd;
return T(*val);}
4235 case kBits: {UInt_t *val = (UInt_t*)ladd;
return T(*val);}
4238 case kOffsetL + kBool: {Bool_t *val = (Bool_t*)ladd;
return T(val[k]);}
4239 case kOffsetL + kChar: {Char_t *val = (Char_t*)ladd;
return T(val[k]);}
4240 case kOffsetL + kShort: {Short_t *val = (Short_t*)ladd;
return T(val[k]);}
4241 case kOffsetL + kInt: {Int_t *val = (Int_t*)ladd;
return T(val[k]);}
4242 case kOffsetL + kLong: {Long_t *val = (Long_t*)ladd;
return T(val[k]);}
4243 case kOffsetL + kLong64: {Long64_t *val = (Long64_t*)ladd;
return T(val[k]);}
4244 case kOffsetL + kFloat: {Float_t *val = (Float_t*)ladd;
return T(val[k]);}
4245 case kOffsetL + kFloat16: {Float_t *val = (Float_t*)ladd;
return T(val[k]);}
4246 case kOffsetL + kDouble: {Double_t *val = (Double_t*)ladd;
return T(val[k]);}
4247 case kOffsetL + kDouble32:{Double_t *val = (Double_t*)ladd;
return T(val[k]);}
4248 case kOffsetL + kUChar: {UChar_t *val = (UChar_t*)ladd;
return T(val[k]);}
4249 case kOffsetL + kUShort: {UShort_t *val = (UShort_t*)ladd;
return T(val[k]);}
4250 case kOffsetL + kUInt: {UInt_t *val = (UInt_t*)ladd;
return T(val[k]);}
4251 case kOffsetL + kULong: {ULong_t *val = (ULong_t*)ladd;
return T(val[k]);}
4252 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
4253 case kOffsetL + kULong64: {Long64_t *val = (Long64_t*)ladd;
return T(val[k]);}
4255 case kOffsetL + kULong64:{ULong64_t *val= (ULong64_t*)ladd;
return T(val[k]);}
4258 #define READ_ARRAY(TYPE_t) \
4260 Int_t sub_instance, index; \
4261 Int_t instance = k; \
4263 index = instance / len; \
4264 sub_instance = instance % len; \
4269 TYPE_t **val =(TYPE_t**)(ladd); \
4270 return T((val[sub_instance])[index]); \
4274 case kOffsetP + kBool_t: READ_ARRAY(Bool_t)
4275 case kOffsetP + kChar_t: READ_ARRAY(Char_t)
4276 case kOffsetP + kShort_t: READ_ARRAY(Short_t)
4277 case kOffsetP + kInt_t: READ_ARRAY(Int_t)
4278 case kOffsetP + kLong_t: READ_ARRAY(Long_t)
4279 case kOffsetP + kLong64_t: READ_ARRAY(Long64_t)
4280 case kOffsetP + kFloat16_t:
4281 case kOffsetP + kFloat_t: READ_ARRAY(Float_t)
4282 case kOffsetP + kDouble32_t:
4283 case kOffsetP + kDouble_t: READ_ARRAY(Double_t)
4284 case kOffsetP + kUChar_t: READ_ARRAY(UChar_t)
4285 case kOffsetP + kUShort_t: READ_ARRAY(UShort_t)
4286 case kOffsetP + kUInt_t: READ_ARRAY(UInt_t)
4287 case kOffsetP + kULong_t: READ_ARRAY(ULong_t)
4288 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
4289 case kOffsetP + kULong64_t: READ_ARRAY(Long64_t)
4291 case kOffsetP + kULong64_t: READ_ARRAY(ULong64_t)
4295 case kCounter: {Int_t *val = (Int_t*)ladd;
return T(*val);}
4302 template Double_t TStreamerInfo::GetTypedValue(
char *pointer, Int_t i, Int_t j, Int_t len)
const;
4303 template Long64_t TStreamerInfo::GetTypedValue(
char *pointer, Int_t i, Int_t j, Int_t len)
const;
4304 template LongDouble_t TStreamerInfo::GetTypedValue(
char *pointer, Int_t i, Int_t j, Int_t len)
const;
4312 template <
typename T>
4313 T TStreamerInfo::GetTypedValue(
char *pointer, Int_t i, Int_t j, Int_t len)
const
4321 if (i < 0)
return 0;
4322 ladd = pointer + fCompFull[i]->fOffset;
4323 atype = fCompFull[i]->fNewType;
4324 len = fCompFull[i]->fElem->GetArrayLength();
4325 if (atype == kSTL) {
4326 TClass *newClass = fCompFull[i]->fElem->GetNewClass();
4327 if (newClass == 0) {
4328 newClass = fCompFull[i]->fElem->GetClassPointer();
4330 TClass *innerClass = newClass->GetCollectionProxy()->GetValueClass();
4334 TVirtualCollectionProxy *proxy = newClass->GetCollectionProxy();
4336 atype = (TStreamerInfo::EReadWrite)proxy->GetType();
4337 TVirtualCollectionProxy::TPushPop pop(proxy,ladd);
4338 Int_t nc = proxy->Size();
4339 if (j >= nc)
return 0;
4340 char *element_ptr = (
char*)proxy->At(j);
4341 return GetTypedValueAux<T>(atype,element_ptr,0,1);
4345 return GetTypedValueAux<T>(atype,ladd,j,len);
4350 template Double_t TStreamerInfo::GetTypedValueClones<Double_t>(TClonesArray *clones, Int_t i, Int_t j,
int k, Int_t eoffset)
const;
4351 template Long64_t TStreamerInfo::GetTypedValueClones(TClonesArray *clones, Int_t i, Int_t j,
int k, Int_t eoffset)
const;
4352 template LongDouble_t TStreamerInfo::GetTypedValueClones(TClonesArray *clones, Int_t i, Int_t j,
int k, Int_t eoffset)
const;
4354 template <
typename T>
4355 T TStreamerInfo::GetTypedValueClones(TClonesArray *clones, Int_t i, Int_t j,
int k, Int_t eoffset)
const
4360 Int_t nc = clones->GetEntriesFast();
4361 if (j >= nc)
return 0;
4363 char *pointer = (
char*)clones->UncheckedAt(j);
4364 char *ladd = pointer + eoffset + fCompFull[i]->fOffset;
4365 return GetTypedValueAux<T>(fCompFull[i]->fType,ladd,k,((TStreamerElement*)fCompFull[i]->fElem)->GetArrayLength());
4368 template Double_t TStreamerInfo::GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j,
int k, Int_t eoffset)
const;
4369 template Long64_t TStreamerInfo::GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j,
int k, Int_t eoffset)
const;
4370 template LongDouble_t TStreamerInfo::GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j,
int k, Int_t eoffset)
const;
4376 template <
typename T>
4377 T TStreamerInfo::GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j,
int k, Int_t eoffset)
const
4379 Int_t nc = cont->Size();
4380 if (j >= nc)
return 0;
4382 char *pointer = (
char*)cont->At(j);
4383 char *ladd = pointer + eoffset + fCompFull[i]->fOffset;
4384 return GetTypedValueAux<T>(fCompFull[i]->fType,ladd,k,((TStreamerElement*)fCompFull[i]->fElem)->GetArrayLength());
4387 template Double_t TStreamerInfo::GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j,
int k, Int_t eoffset)
const;
4388 template Long64_t TStreamerInfo::GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j,
int k, Int_t eoffset)
const;
4389 template LongDouble_t TStreamerInfo::GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j,
int k, Int_t eoffset)
const;
4395 template <
typename T>
4396 T TStreamerInfo::GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j,
int k, Int_t eoffset)
const
4398 Int_t nc = cont->Size();
4400 if (j >= nc)
return 0;
4402 char **ptr = (
char**)cont->At(j);
4403 char *pointer = *ptr;
4405 char *ladd = pointer + eoffset + fCompFull[i]->fOffset;
4406 return GetTypedValueAux<T>(fCompFull[i]->fType,ladd,k,((TStreamerElement*)fCompFull[i]->fElem)->GetArrayLength());
4412 void TStreamerInfo::InsertArtificialElements(std::vector<const ROOT::TSchemaRule*> &rules)
4414 if (rules.empty())
return;
4416 TIter next(fElements);
4419 for(
auto rule : rules) {
4420 if( rule->IsRenameRule() || rule->IsAliasRule() )
4423 TStreamerElement *element;
4424 while ((element = (TStreamerElement*) next())) {
4425 if ( rule->HasTarget( element->GetName() ) ) {
4428 if ( rule->GetAttributes()[0] != 0 ) {
4429 TString attr( rule->GetAttributes() );
4431 if (attr.Contains(
"owner")) {
4432 if (attr.Contains(
"notowner")) {
4433 element->SetBit(TStreamerElement::kDoNotDelete);
4435 element->ResetBit(TStreamerElement::kDoNotDelete);
4446 const TObjArray *sources = rule->GetSource();
4447 TIter input(sources);
4449 while((src = input())) {
4450 if ( !GetElements()->FindObject(src->GetName()) ) {
4452 #if 0 // Don't warn about not activating the rule. If don't warn the user can
4458 rule->AsString(ruleStr);
4459 Warning(
"InsertArtificialElements",
"For class %s in StreamerInfo %d is missing the source data member %s when trying to apply the rule:\n %s",
4460 GetName(),GetClassVersion(),src->GetName(),ruleStr.Data());
4467 if (!rule)
continue;
4469 TStreamerArtificial *newel;
4470 typedef std::vector<TStreamerArtificial*> vec_t;
4473 if (rule->GetTarget()==0) {
4475 newName.Form(
"%s_rule%d",fClass->GetName(),count);
4476 newel =
new TStreamerArtificial(newName,
"",
4477 fClass->GetDataMemberOffset(newName),
4478 TStreamerInfo::kArtificial,
4480 newel->SetBit(TStreamerElement::kWholeObject);
4481 newel->SetReadFunc( rule->GetReadFunctionPointer() );
4482 newel->SetReadRawFunc( rule->GetReadRawFunctionPointer() );
4483 toAdd.push_back(newel);
4485 toAdd.reserve(rule->GetTarget()->GetEntries());
4486 TObjString * objstr = (TObjString*)(rule->GetTarget()->At(0));
4488 TString newName = objstr->String();
4489 TString realDataName;
4490 if ( TDataMember* dm = fClass->GetDataMember( newName ) ) {
4491 TRealData::GetName(realDataName,dm);
4492 newel =
new TStreamerArtificial(realDataName,
"",
4493 fClass->GetDataMemberOffset(newName),
4494 TStreamerInfo::kArtificial,
4495 fClass->GetDataMember( newName )->GetTypeName());
4496 newel->SetReadFunc( rule->GetReadFunctionPointer() );
4497 newel->SetReadRawFunc( rule->GetReadRawFunctionPointer() );
4498 toAdd.push_back(newel);
4503 for(Int_t other = 1; other < rule->GetTarget()->GetEntries(); ++other) {
4504 objstr = (TObjString*)(rule->GetTarget()->At(other));
4506 newName = objstr->String();
4507 if ( TDataMember* dm = fClass->GetDataMember( newName ) ) {
4508 TRealData::GetName(realDataName,dm);
4509 newel =
new TStreamerArtificial(realDataName,
"",
4510 fClass->GetDataMemberOffset(newName),
4511 TStreamerInfo::kArtificial,
4512 fClass->GetDataMember( newName )->GetTypeName());
4513 toAdd.push_back(newel);
4520 TIter s_iter(rule->GetSource());
4522 while( TObjString *s = (TObjString*)s_iter() ) {
4523 for(Int_t i = fElements->GetLast(); i >= 0 && (i+1) >= loc; --i) {
4524 if (s->String() == fElements->UncheckedAt(i)->GetName()) {
4525 if (loc == -1 || (i+1)>loc) {
4533 for(Int_t i = fElements->GetLast(); i >= 0 && (i+1) >= loc; --i) {
4534 if ( ((TStreamerElement*)fElements->UncheckedAt(i))->GetNewType() != -2 ) {
4541 for(vec_t::iterator iter = toAdd.begin(); iter != toAdd.end(); ++iter) {
4542 fElements->Add(*iter);
4545 R__TObjArray_InsertAt(fElements, toAdd, loc);
4555 void TStreamerInfo::ls(Option_t *option)
const
4557 if (fClass && (fName != fClass->GetName())) {
4558 if (fClass->IsVersioned()) {
4559 Printf(
"\nStreamerInfo for conversion to %s from: %s, version=%d, checksum=0x%x",fClass->GetName(),GetName(),fClassVersion,GetCheckSum());
4561 Printf(
"\nStreamerInfo for conversion to %s from: %s, checksum=0x%x",fClass->GetName(),GetName(),GetCheckSum());
4564 if (!fClass || fClass->IsVersioned()) {
4565 Printf(
"\nStreamerInfo for class: %s, version=%d, checksum=0x%x",GetName(),fClassVersion,GetCheckSum());
4567 Printf(
"\nStreamerInfo for class: %s, checksum=0x%x",GetName(),GetCheckSum());
4572 TIter next(fElements);
4574 while ((obj = next()))
4577 if (strstr(option,
"full") != 0) {
4578 for (Int_t i=0; i < fNfulldata; ++i) {
4579 TStreamerElement *element = (TStreamerElement*)fCompFull[i]->fElem;
4580 TString sequenceType;
4581 element->GetSequenceType(sequenceType);
4583 if (sequenceType.Length()) {
4584 sequenceType.Prepend(
" [");
4585 sequenceType +=
"]";
4587 Printf(
" i=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld%s",
4588 i,element->GetName(),fCompFull[i]->fType,fCompFull[i]->fOffset,fCompFull[i]->fLength,fCompFull[i]->fMethod,
4589 sequenceType.Data());
4593 Bool_t wantOrig = strstr(option,
"incOrig") != 0;
4594 Bool_t optimized = kFALSE;
4595 for (Int_t i=0,j=0;i < fNdata;++i,++j) {
4596 TStreamerElement *element = (TStreamerElement*)fCompOpt[i]->fElem;
4597 TString sequenceType;
4598 element->GetSequenceType(sequenceType);
4600 optimized = TStreamerInfo::kOffsetL < fCompOpt[i]->fType && fCompOpt[i]->fType < TStreamerInfo::kOffsetP && fCompOpt[i]->fLength > fCompOpt[i]->fElem->GetArrayLength();
4603 if (sequenceType.Length() != 0) {
4604 sequenceType +=
',';
4606 sequenceType +=
"optimized";
4608 if (sequenceType.Length()) {
4609 sequenceType.Prepend(
" [");
4610 sequenceType +=
"]";
4612 Printf(
" i=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld%s",
4613 i,element->GetName(),fCompOpt[i]->fType,fCompOpt[i]->fOffset,fCompOpt[i]->fLength,fCompOpt[i]->fMethod,
4614 sequenceType.Data());
4615 if (optimized && wantOrig) {
4618 element = (TStreamerElement*)fCompFull[j]->fElem;
4619 element->GetSequenceType(sequenceType);
4620 if (sequenceType.Length()) {
4621 sequenceType.Prepend(
" [");
4622 sequenceType +=
"]";
4624 Printf(
" j=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld%s",
4625 j,element->GetName(),fCompFull[j]->fType,fCompFull[j]->fOffset,fCompFull[j]->fLength,fCompFull[j]->fMethod,
4626 sequenceType.Data());
4628 done = j >= fNfulldata || ( (i+1 < fNdata) && fCompOpt[i+1]->fElem == fCompFull[j+1]->fElem );
4640 void* TStreamerInfo::New(
void *obj)
4644 char* p = (
char*) obj;
4646 TIter next(fElements);
4650 p =
new char[fSize];
4651 memset(p, 0, fSize);
4655 TStreamerElement* element = (TStreamerElement*) next();
4657 for (; element; element = (TStreamerElement*) next()) {
4660 if (element->GetOffset() == kMissing) {
4666 TClass* cle = element->GetClassPointer();
4671 char* eaddr = p + element->GetOffset();
4672 Int_t etype = element->GetType();
4683 char** r = (
char**) eaddr;
4684 Int_t len = element->GetArrayLength();
4685 for (Int_t i = 0; i < len; ++i) {
4697 if (cle != TClonesArray::Class()) {
4698 void** r = (
void**) eaddr;
4705 const char* title = element->GetTitle();
4706 const char* bracket1 = strrchr(title,
'(');
4707 const char* bracket2 = strrchr(title,
')');
4708 if (bracket1 && bracket2 && (bracket2 != (bracket1 + 1))) {
4709 Int_t len = bracket2 - (bracket1 + 1);
4710 char* clonesClass =
new char[len+1];
4711 clonesClass[0] =
'\0';
4712 strncat(clonesClass, bracket1 + 1, len);
4713 void** r = (
void**) eaddr;
4714 *r = (
void*)
new TClonesArray(clonesClass);
4715 delete[] clonesClass;
4718 void** r = (
void**) eaddr;
4719 *r = (
void*)
new TClonesArray();
4727 if (cle->Property() & kIsAbstract) {
4728 TVirtualStreamerInfo *einfo = cle->GetStreamerInfoAbstractEmulated();
4729 if (einfo) einfo->New(eaddr);
4747 if (strcmp(element->GetName(),
"This")==0 &&
4748 !cle->GetCollectionProxy()) {
4757 case kObject + kOffsetL:
4758 case kAny + kOffsetL:
4759 case kTObject + kOffsetL:
4760 case kTString + kOffsetL:
4761 case kTNamed + kOffsetL:
4762 case kSTL + kOffsetL:
4764 Int_t size = cle->Size();
4766 Int_t len = element->GetArrayLength();
4767 for (Int_t i = 0; i < len; ++i, r += size) {
4776 for(
int nbase = 0; nbase < fNVirtualInfoLoc; ++nbase) {
4777 *(TStreamerInfo**)(p + fVirtualInfoLoc[nbase]) =
this;
4787 void* TStreamerInfo::NewArray(Long_t nElements,
void *ary)
4790 Error(
"NewArray",
"TClass pointer is null!");
4794 Int_t size = fClass->Size();
4796 char* p = (
char*) ary;
4799 Long_t len = nElements * size +
sizeof(Long_t)*2;
4805 Long_t* r = (Long_t*) p;
4808 char* dataBegin = (
char*) &r[2];
4812 for (Long_t cnt = 0; cnt < nElements; ++cnt) {
4821 #define DeleteBasicPointer(addr,element,name) \
4823 name **f = (name**)(addr); \
4824 int n = element->GetArrayLength() ? element->GetArrayLength() : 1;\
4825 for(int j=0;j<n;j++) { \
4836 void TStreamerInfo::DestructorImpl(
void* obj, Bool_t dtorOnly)
4838 R__ASSERT(obj != 0);
4840 char *p = (
char*)obj;
4842 Int_t nelements = fElements->GetEntriesFast();
4844 for (Int_t elenum = nelements - 1; elenum >= 0; --elenum) {
4845 TStreamerElement* ele = (TStreamerElement*) fElements->UncheckedAt(elenum);
4846 if (ele->GetOffset() == kMissing)
continue;
4847 char* eaddr = p + ele->GetOffset();
4850 Int_t etype = ele->GetType();
4853 case TStreamerInfo::kOffsetP + TStreamerInfo::kBool: DeleteBasicPointer(eaddr,ele,Bool_t);
continue;
4854 case TStreamerInfo::kOffsetP + TStreamerInfo::kChar: DeleteBasicPointer(eaddr,ele,Char_t);
continue;
4855 case TStreamerInfo::kOffsetP + TStreamerInfo::kShort: DeleteBasicPointer(eaddr,ele,Short_t);
continue;
4856 case TStreamerInfo::kOffsetP + TStreamerInfo::kInt: DeleteBasicPointer(eaddr,ele,Int_t);
continue;
4857 case TStreamerInfo::kOffsetP + TStreamerInfo::kLong: DeleteBasicPointer(eaddr,ele,Long_t);
continue;
4858 case TStreamerInfo::kOffsetP + TStreamerInfo::kLong64: DeleteBasicPointer(eaddr,ele,Long64_t);
continue;
4859 case TStreamerInfo::kOffsetP + TStreamerInfo::kFloat16:
4860 case TStreamerInfo::kOffsetP + TStreamerInfo::kFloat: DeleteBasicPointer(eaddr,ele,Float_t);
continue;
4861 case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble32:
4862 case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble: DeleteBasicPointer(eaddr,ele,Double_t);
continue;
4863 case TStreamerInfo::kOffsetP + TStreamerInfo::kUChar: DeleteBasicPointer(eaddr,ele,UChar_t);
continue;
4864 case TStreamerInfo::kOffsetP + TStreamerInfo::kUShort: DeleteBasicPointer(eaddr,ele,UShort_t);
continue;
4865 case TStreamerInfo::kOffsetP + TStreamerInfo::kUInt: DeleteBasicPointer(eaddr,ele,UInt_t);
continue;
4866 case TStreamerInfo::kOffsetP + TStreamerInfo::kULong: DeleteBasicPointer(eaddr,ele,ULong_t);
continue;
4867 case TStreamerInfo::kOffsetP + TStreamerInfo::kULong64:DeleteBasicPointer(eaddr,ele,ULong64_t);
continue;
4868 case TStreamerInfo::kCharStar: DeleteBasicPointer(eaddr,ele,Char_t);
continue;
4873 TClass* cle = ele->GetClassPointer();
4877 if (etype == kObjectp || etype == kAnyp) {
4879 Int_t len = ele->GetArrayLength();
4883 void** r = (
void**) eaddr;
4884 for (Int_t j = len - 1; j >= 0; --j) {
4886 cle->Destructor(r[j]);
4892 if ((etype == kObjectP || etype == kAnyP || etype == kSTLp) && !ele->TestBit(TStreamerElement::kDoNotDelete)) {
4894 Int_t len = ele->GetArrayLength();
4898 void** r = (
void**) eaddr;
4899 for (Int_t j = len - 1; j >= 0; --j) {
4901 cle->Destructor(r[j]);
4907 if (etype == kBase) {
4908 if (cle->Property() & kIsAbstract) {
4909 TVirtualStreamerInfo *einfo = cle->GetStreamerInfoAbstractEmulated();
4910 if (einfo) einfo->Destructor(eaddr, kTRUE);
4912 cle->Destructor(eaddr, kTRUE);
4916 if (etype == kObject || etype == kAny ||
4917 etype == kTObject || etype == kTString || etype == kTNamed) {
4919 cle->Destructor(eaddr, kTRUE);
4922 if (etype == kSTL) {
4924 TVirtualCollectionProxy *pr = cle->GetCollectionProxy();
4926 if (strcmp(ele->GetName(),
"This")==0) {
4930 cle->Destructor(eaddr, kTRUE);
4933 if (ele->TestBit(TStreamerElement::kDoNotDelete)) {
4934 TVirtualCollectionProxy::TPushPop env(cle->GetCollectionProxy(), eaddr);
4935 cle->GetCollectionProxy()->Clear();
4936 pr->Destructor(eaddr, kTRUE);
4938 pr->Destructor(eaddr, kTRUE);
4943 if (etype == kObject + kOffsetL || etype == kAny + kOffsetL ||
4944 etype == kTObject + kOffsetL || etype == kTString + kOffsetL ||
4945 etype == kTNamed + kOffsetL || etype == kSTL + kOffsetL) {
4948 Int_t len = ele->GetArrayLength();
4949 Int_t size = cle->Size();
4950 char* r = eaddr + (size * (len - 1));
4951 for (Int_t j = len - 1; j >= 0; --j, r -= size) {
4952 cle->Destructor(r, kTRUE);
4970 void TStreamerInfo::Destructor(
void* obj, Bool_t dtorOnly)
4973 if (obj == 0)
return;
4975 char* p = (
char*) obj;
4977 if (!dtorOnly && fNVirtualInfoLoc) {
4980 TStreamerInfo *allocator = *(TStreamerInfo**)(p + fVirtualInfoLoc[0]);
4981 if (allocator !=
this) {
4983 Int_t baseoffset = allocator->GetClass()->GetBaseClassOffset(GetClass());
4986 allocator->DestructorImpl(p, kFALSE);
4990 DestructorImpl(p, dtorOnly);
4996 void TStreamerInfo::DeleteArray(
void* ary, Bool_t dtorOnly)
4999 if (ary == 0)
return;
5003 Long_t* r = (Long_t*) ary;
5004 Long_t arrayLen = r[-1];
5005 Long_t size = r[-2];
5006 char* memBegin = (
char*) &r[-2];
5008 char* p = ((
char*) ary) + ((arrayLen - 1) * size);
5009 for (Long_t cnt = 0; cnt < arrayLen; ++cnt, p -= size) {
5011 Destructor(p, kTRUE);
5029 void TStreamerInfo::PrintValue(
const char *name,
char *pointer, Int_t i, Int_t len, Int_t lenmax)
const
5033 printf(
" %-15s = ",name);
5035 TStreamerElement * aElement = 0;
5046 const static TClassRef stringClass(
"string");
5047 if (fClass == stringClass) {
5048 std::string *st = (std::string*)(pointer);
5049 printf(
"%s\n",st->c_str());
5050 }
else if (fClass == TString::Class()) {
5051 TString *st = (TString*)(pointer);
5052 printf(
"%s\n",st->Data());
5054 printf(
"(%s*)0x%lx\n",GetName(),(ULong_t)pointer);
5059 ladd = pointer + fCompFull[i]->fOffset;
5060 atype = fCompFull[i]->fNewType;
5061 aleng = fCompFull[i]->fLength;
5062 aElement = (TStreamerElement*)fCompFull[i]->fElem;
5063 count = (Int_t*)(pointer+fCompFull[i]->fMethod);
5065 if (aleng > lenmax) aleng = lenmax;
5067 PrintValueAux(ladd,atype,aElement,aleng,count);
5074 void TStreamerInfo::PrintValueClones(
const char *name, TClonesArray *clones, Int_t i, Int_t eoffset, Int_t lenmax)
const
5076 if (!clones) {printf(
" %-15s = \n",name);
return;}
5077 printf(
" %-15s = ",name);
5078 Int_t nc = clones->GetEntriesFast();
5079 if (nc > lenmax) nc = lenmax;
5081 Int_t offset = eoffset + fCompFull[i]->fOffset;
5082 TStreamerElement *aElement = (TStreamerElement*)fCompFull[i]->fElem;
5083 int aleng = fCompFull[i]->fLength;
5084 if (aleng > lenmax) aleng = lenmax;
5086 for (Int_t k=0;k < nc;k++) {
5087 char *pointer = (
char*)clones->UncheckedAt(k);
5088 char *ladd = pointer+offset;
5089 Int_t *count = (Int_t*)(pointer+fCompFull[i]->fMethod);
5090 PrintValueAux(ladd,fCompFull[i]->fNewType,aElement, aleng, count);
5091 if (k < nc-1) printf(
", ");
5099 void TStreamerInfo::PrintValueSTL(
const char *name, TVirtualCollectionProxy *cont, Int_t i, Int_t eoffset, Int_t lenmax)
const
5101 if (!cont) {printf(
" %-15s = \n",name);
return;}
5102 printf(
" %-15s = ",name);
5103 Int_t nc = cont->Size();
5104 if (nc > lenmax) nc = lenmax;
5106 Int_t offset = eoffset + fCompFull[i]->fOffset;
5107 TStreamerElement *aElement = (TStreamerElement*)fCompFull[i]->fElem;
5108 int aleng = fCompFull[i]->fLength;
5109 if (aleng > lenmax) aleng = lenmax;
5111 for (Int_t k=0;k < nc;k++) {
5112 char *pointer = (
char*)cont->At(k);
5113 char *ladd = pointer+offset;
5114 Int_t *count = (Int_t*)(pointer+fCompFull[i]->fMethod);
5115 PrintValueAux(ladd,fCompFull[i]->fNewType,aElement, aleng, count);
5116 if (k < nc-1) printf(
", ");
5124 void TStreamerInfo::Streamer(TBuffer &R__b)
5127 if (R__b.IsReading()) {
5128 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
5132 R__b.ClassBegin(TStreamerInfo::Class(), R__v);
5133 R__b.ClassMember(
"TNamed");
5134 TNamed::Streamer(R__b);
5135 fName = TClassEdit::GetLong64_Name( fName.Data() ).c_str();
5136 R__b.ClassMember(
"fCheckSum",
"UInt_t");
5138 R__b.ClassMember(
"fClassVersion",
"Int_t");
5139 R__b >> fClassVersion;
5140 fOnFileClassVersion = fClassVersion;
5141 R__b.ClassMember(
"fElements",
"TObjArray*");
5143 R__b.ClassEnd(TStreamerInfo::Class());
5144 R__b.SetBufferOffset(R__s+R__c+
sizeof(UInt_t));
5145 ResetBit(kIsCompiled);
5146 ResetBit(kBuildOldUsed);
5147 ResetBit(kBuildRunning);
5149 if (R__b.GetParent() && R__b.GetVersionOwner() < 50000)
5153 Int_t nobjects = fElements->GetEntriesFast();
5154 TClass *basic = TStreamerBasicType::Class();
5155 for (Int_t i = 0; i < nobjects; i++) {
5156 TStreamerElement *el = (TStreamerElement*)fElements->UncheckedAt(i);
5157 TStreamerElement *rel = 0;
5158 if ( el->IsA() == basic ) {
5159 switch (el->GetType()) {
5161 case TStreamerInfo::kObject:
5162 rel =
new TStreamerObject(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5164 case TStreamerInfo::kAny:
5165 rel =
new TStreamerObjectAny(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5167 case TStreamerInfo::kObjectp:
5168 rel =
new TStreamerObjectPointer(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5170 case TStreamerInfo::kObjectP:
5171 rel =
new TStreamerObjectPointer(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5173 case TStreamerInfo::kTString:
5174 rel =
new TStreamerObject(el->GetName(),el->GetTitle(),el->GetOffset(),el->GetTypeName());
5178 (*fElements)[i] = rel;
5187 TNamed::Streamer(R__b);
5188 fName = TClassEdit::GetLong64_Name( fName.Data() ).c_str();
5190 R__b >> fClassVersion;
5191 fOnFileClassVersion = fClassVersion;
5193 R__b.CheckByteCount(R__s, R__c, TStreamerInfo::IsA());
5195 R__c = R__b.WriteVersion(TStreamerInfo::IsA(), kTRUE);
5196 R__b.ClassBegin(TStreamerInfo::Class());
5197 R__b.ClassMember(
"TNamed");
5198 TNamed::Streamer(R__b);
5199 R__b.ClassMember(
"fCheckSum",
"UInt_t");
5201 R__b.ClassMember(
"fClassVersion",
"Int_t");
5202 R__b << ((fClassVersion > 0) ? fClassVersion : -fClassVersion);
5208 R__b.ClassMember(
"fElements",
"TObjArray*");
5210 TObjArray elements(fElements->GetEntriesFast());
5211 TStreamerElement *el;
5212 Int_t nobjects = fElements->GetEntriesFast();
5213 for (Int_t i = 0; i < nobjects; i++) {
5214 el = (TStreamerElement *)fElements->UncheckedAt(i);
5215 if (el != 0 && (el->IsA() == TStreamerArtificial::Class() || el->TestBit(TStreamerElement::kRepeat))) {
5217 }
else if (el != 0 && (el->TestBit(TStreamerElement::kCache) && !el->TestBit(TStreamerElement::kWrite))) {
5219 }
else if (el != 0) {
5220 elements.AddLast(el);
5223 R__b.WriteObjectAny(&elements, TObjArray::Class(), kFALSE);
5225 R__b.ClassEnd(TStreamerInfo::Class());
5226 R__b.SetByteCount(R__c, kTRUE);
5235 void TStreamerInfo::TagFile(TFile *file)
5240 static std::atomic<Bool_t> onlyonce(kFALSE);
5241 Bool_t expected = kFALSE;
5242 if (onlyonce.compare_exchange_strong(expected,kTRUE)) {
5243 Warning(
"TagFile",
"This function is deprecated, use TBuffer::TagStreamerInfo instead");
5245 TArrayC *cindex = file->GetClassIndex();
5246 Int_t nindex = cindex->GetSize();
5247 if (fNumber < 0 || fNumber >= nindex) {
5248 Error(
"TagFile",
"StreamerInfo: %s number: %d out of range[0,%d] in file: %s",
5249 GetName(),fNumber,nindex,file->GetName());
5252 if (cindex->fArray[fNumber] == 0) {
5253 cindex->fArray[0] = 1;
5254 cindex->fArray[fNumber] = 1;
5264 #define DOLOOP for (k = 0, pointer = arr[0]; k < narr; pointer = arr[++k])
5267 static void PrintCR(
int j,Int_t aleng, UInt_t ltype)
5269 if (j == aleng-1) printf(
"\n");
5272 if (j%ltype == ltype-1) printf(
"\n ");
5287 void TStreamerInfo::PrintValueAux(
char *ladd, Int_t atype, TStreamerElement *aElement, Int_t aleng, Int_t *count)
5294 case kBool: {Bool_t *val = (Bool_t* )ladd; printf(
"%d" ,*val);
break;}
5295 case kChar: {Char_t *val = (Char_t* )ladd; printf(
"%d" ,*val);
break;}
5296 case kShort: {Short_t *val = (Short_t* )ladd; printf(
"%d" ,*val);
break;}
5297 case kInt: {Int_t *val = (Int_t* )ladd; printf(
"%d" ,*val);
break;}
5298 case kLong: {Long_t *val = (Long_t* )ladd; printf(
"%ld",*val);
break;}
5299 case kLong64: {Long64_t *val = (Long64_t* )ladd; printf(
"%lld",*val);
break;}
5300 case kFloat: {Float_t *val = (Float_t* )ladd; printf(
"%f" ,*val);
break;}
5301 case kFloat16: {Float_t *val = (Float_t* )ladd; printf(
"%f" ,*val);
break;}
5302 case kDouble: {Double_t *val = (Double_t* )ladd; printf(
"%g" ,*val);
break;}
5303 case kDouble32: {Double_t *val = (Double_t* )ladd; printf(
"%g" ,*val);
break;}
5304 case kUChar: {UChar_t *val = (UChar_t* )ladd; printf(
"%u" ,*val);
break;}
5305 case kUShort: {UShort_t *val = (UShort_t* )ladd; printf(
"%u" ,*val);
break;}
5306 case kUInt: {UInt_t *val = (UInt_t* )ladd; printf(
"%u" ,*val);
break;}
5307 case kULong: {ULong_t *val = (ULong_t* )ladd; printf(
"%lu",*val);
break;}
5308 case kULong64: {ULong64_t *val = (ULong64_t*)ladd; printf(
"%llu",*val);
break;}
5309 case kBits: {UInt_t *val = (UInt_t* )ladd; printf(
"%d" ,*val);
break;}
5312 case kOffsetL + kBool: {Bool_t *val = (Bool_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%c " ,(
char)val[j]); PrintCR(j,aleng,20); }
break;}
5313 case kOffsetL + kChar: {Char_t *val = (Char_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%c " ,val[j]); PrintCR(j,aleng,20); }
break;}
5314 case kOffsetL + kShort: {Short_t *val = (Short_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%d " ,val[j]); PrintCR(j,aleng,10); }
break;}
5315 case kOffsetL + kInt: {Int_t *val = (Int_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%d " ,val[j]); PrintCR(j,aleng,10); }
break;}
5316 case kOffsetL + kLong: {Long_t *val = (Long_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%ld ",val[j]); PrintCR(j,aleng, 5); }
break;}
5317 case kOffsetL + kLong64: {Long64_t *val = (Long64_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%lld ",val[j]);PrintCR(j,aleng, 5); }
break;}
5318 case kOffsetL + kFloat: {Float_t *val = (Float_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%f " ,val[j]); PrintCR(j,aleng, 5); }
break;}
5319 case kOffsetL + kFloat16: {Float_t *val = (Float_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%f " ,val[j]); PrintCR(j,aleng, 5); }
break;}
5320 case kOffsetL + kDouble: {Double_t *val = (Double_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%g " ,val[j]); PrintCR(j,aleng, 5); }
break;}
5321 case kOffsetL + kDouble32:{Double_t *val = (Double_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%g " ,val[j]); PrintCR(j,aleng, 5); }
break;}
5322 case kOffsetL + kUChar: {UChar_t *val = (UChar_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%u " ,val[j]); PrintCR(j,aleng,20); }
break;}
5323 case kOffsetL + kUShort: {UShort_t *val = (UShort_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%u " ,val[j]); PrintCR(j,aleng,10); }
break;}
5324 case kOffsetL + kUInt: {UInt_t *val = (UInt_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%u " ,val[j]); PrintCR(j,aleng, 5); }
break;}
5325 case kOffsetL + kULong: {ULong_t *val = (ULong_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%lu ",val[j]); PrintCR(j,aleng, 5); }
break;}
5326 case kOffsetL + kULong64: {ULong64_t *val = (ULong64_t*)ladd;
for(j=0;j<aleng;j++) { printf(
"%llu ",val[j]);PrintCR(j,aleng, 5); }
break;}
5327 case kOffsetL + kBits: {UInt_t *val = (UInt_t* )ladd;
for(j=0;j<aleng;j++) { printf(
"%d " ,val[j]); PrintCR(j,aleng, 5); }
break;}
5330 case kOffsetP + kBool: {Bool_t **val = (Bool_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%d " ,(*val)[j]); PrintCR(j,aleng,20); }
break;}
5331 case kOffsetP + kChar: {Char_t **val = (Char_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%d " ,(*val)[j]); PrintCR(j,aleng,20); }
break;}
5332 case kOffsetP + kShort: {Short_t **val = (Short_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%d " ,(*val)[j]); PrintCR(j,aleng,10); }
break;}
5333 case kOffsetP + kInt: {Int_t **val = (Int_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%d " ,(*val)[j]); PrintCR(j,aleng,10); }
break;}
5334 case kOffsetP + kLong: {Long_t **val = (Long_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%ld ",(*val)[j]); PrintCR(j,aleng, 5); }
break;}
5335 case kOffsetP + kLong64: {Long64_t **val = (Long64_t**)ladd;
for(j=0;j<*count;j++) { printf(
"%lld ",(*val)[j]); PrintCR(j,aleng, 5); }
break;}
5336 case kOffsetP + kFloat: {Float_t **val = (Float_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%f " ,(*val)[j]); PrintCR(j,aleng, 5); }
break;}
5337 case kOffsetP + kFloat16: {Float_t **val = (Float_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%f " ,(*val)[j]); PrintCR(j,aleng, 5); }
break;}
5338 case kOffsetP + kDouble: {Double_t **val = (Double_t**)ladd;
for(j=0;j<*count;j++) { printf(
"%g " ,(*val)[j]); PrintCR(j,aleng, 5); }
break;}
5339 case kOffsetP + kDouble32:{Double_t **val = (Double_t**)ladd;
for(j=0;j<*count;j++) { printf(
"%g " ,(*val)[j]); PrintCR(j,aleng, 5); }
break;}
5340 case kOffsetP + kUChar: {UChar_t **val = (UChar_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%u " ,(*val)[j]); PrintCR(j,aleng,20); }
break;}
5341 case kOffsetP + kUShort: {UShort_t **val = (UShort_t**)ladd;
for(j=0;j<*count;j++) { printf(
"%u " ,(*val)[j]); PrintCR(j,aleng,10); }
break;}
5342 case kOffsetP + kUInt: {UInt_t **val = (UInt_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%u " ,(*val)[j]); PrintCR(j,aleng, 5); }
break;}
5343 case kOffsetP + kULong: {ULong_t **val = (ULong_t** )ladd;
for(j=0;j<*count;j++) { printf(
"%lu ",(*val)[j]); PrintCR(j,aleng, 5); }
break;}
5344 case kOffsetP + kULong64: {ULong64_t**val = (ULong64_t**)ladd;
for(j=0;j<*count;j++){ printf(
"%llu ",(*val)[j]); PrintCR(j,aleng, 5); }
break;}
5347 case kCounter: {Int_t *val = (Int_t*)ladd; printf(
"%d",*val);
break;}
5350 char **val = (
char**)ladd;
5351 if (*val) printf(
"%s",*val);
5356 TObject **obj = (TObject**)(ladd);
5357 TStreamerObjectPointer *el = (TStreamerObjectPointer*)aElement;
5358 printf(
"(%s*)%lx",el ? el->GetClass()->GetName() :
"unknown_type",(Long_t)(*obj));
5364 TObject **obj = (TObject**)(ladd);
5365 TStreamerObjectPointer *el = (TStreamerObjectPointer*)aElement;
5366 printf(
"(%s*)%lx",el ? el->GetClass()->GetName() :
"unknown_type",(Long_t)(*obj));
5372 TObject *obj = (TObject*)(ladd);
5373 printf(
"%s",obj->GetName());
5379 TString *st = (TString*)(ladd);
5380 printf(
"%s",st->Data());
5384 TObject *obj = (TObject*)(ladd);
5385 printf(
"%s",obj->GetName());
5389 TNamed *named = (TNamed*) (ladd);
5390 printf(
"%s/%s",named->GetName(),named->GetTitle());
5396 TObject **obj = (TObject**)(ladd);
5397 TStreamerObjectAnyPointer *el = (TStreamerObjectAnyPointer*)aElement;
5398 printf(
"(%s*)0x%lx",el ? el->GetClass()->GetName() :
"unknown_type",(Long_t)(*obj));
5404 TObject **obj = (TObject**)(ladd);
5405 TStreamerObjectAnyPointer *el = (TStreamerObjectAnyPointer*)aElement;
5406 printf(
"(%s*)0x%lx",el ? el->GetClass()->GetName() :
"unknown_type",(Long_t)(*obj));
5410 case kOffsetL + kObjectp:
5411 case kOffsetL + kObjectP:
5413 printf(
"printing kAny case (%d)",atype);
5427 printf(
"printing kBase case (%d)",atype);
5432 case kOffsetL + kObject:
5433 case kOffsetL + kTString:
5434 case kOffsetL + kTObject:
5435 case kOffsetL + kTNamed:
5437 printf(
"printing kStreamer case (%d)",atype);
5452 printf(
"printing kStreamLoop case (%d)",atype);
5468 static TClassRef stringClass(
"string");
5469 if (ladd && aElement->GetClass() == stringClass) {
5470 std::string *st = (std::string*)(ladd);
5471 printf(
"%s",st->c_str());
5473 printf(
"(%s*)0x%lx",aElement->GetClass()->GetName(),(Long_t)(ladd));
5476 printf(
"(unknown_type*)0x%lx",(Long_t)(ladd));
5487 void TStreamerInfo::Update(
const TClass *oldcl, TClass *newcl)
5489 TStreamerElement *element;
5490 TIter nextElement(GetElements());
5491 while ((element = (TStreamerElement*)nextElement())) {
5492 element->Update(oldcl,newcl);
5494 for (Int_t i=0;i < fNslots;i++) {
5495 fComp[i].Update(oldcl,newcl);
5502 void TStreamerInfo::TCompInfo::Update(
const TClass *oldcl, TClass *newcl)
5505 if (fClass == oldcl || strcmp(fClassName, newcl->GetName()) == 0)
5507 else if (fClass == 0 && TClassTable::GetDict(fClassName))
5508 fClass = TClass::GetClass(fClassName);
5515 TVirtualCollectionProxy*
5516 TStreamerInfo::GenEmulatedProxy(
const char* class_name, Bool_t silent)
5518 return TCollectionProxyFactory::GenEmulatedProxy(class_name, silent);
5525 TStreamerInfo::GenEmulatedClassStreamer(
const char* class_name, Bool_t silent)
5527 return TCollectionProxyFactory::GenEmulatedClassStreamer(class_name, silent);
5533 TVirtualCollectionProxy*
5534 TStreamerInfo::GenExplicitProxy( const ::ROOT::TCollectionProxyInfo &info, TClass *cl )
5536 return TCollectionProxyFactory::GenExplicitProxy(info, cl);
5543 TStreamerInfo::GenExplicitClassStreamer( const ::ROOT::TCollectionProxyInfo &info, TClass *cl )
5545 return TCollectionProxyFactory::GenExplicitClassStreamer(info, cl);