17 #include "TClonesArray.h"
18 #include "TStreamerElement.h"
21 #include "TVirtualCollectionProxy.h"
22 #include "TVirtualCollectionIterators.h"
23 #include "TBranchRef.h"
24 #include "TClassEdit.h"
27 #include "TStreamerInfo.h"
28 #include "TBufferFile.h"
29 #include "TVirtualArray.h"
50 TVirtualCollectionProxy* fProxy;
51 TPushPopSafe (TVirtualCollectionProxy*
proxy,
void* objectstart);
52 inline ~TPushPopSafe();
66 inline TPushPopSafe::TPushPopSafe (TVirtualCollectionProxy*
proxy,
71 fProxy->PushProxy (objectstart);
81 inline TPushPopSafe::~TPushPopSafe()
96 void RemovePrefix(TString&
str,
const char*
prefix)
113 std::string BasenameOfBranch (
const std::string& fullname)
115 std::string
s = fullname;
116 size_t pos =
s.rfind(
'.');
117 if (
pos != std::string::npos) {
120 while ((
pos =
s.rfind(
'[')) != std::string::npos) {
136 TStreamerInfo* GetStreamerInfoFromFile (
const TClass*
cl,
const TBranch*
br)
140 TDirectory*
dir =
br->GetDirectory();
141 if (!
dir)
return nullptr;
143 if (!
file)
return nullptr;
144 if (
file->GetSeekInfo() == 0)
return nullptr;
147 const TList* silist =
file->GetStreamerInfoCache();
148 TListIter li (silist);
150 while ((
info =
dynamic_cast<TStreamerInfo*
> (li.Next())) !=
nullptr) {
151 if (strcmp (
info->GetName(),
cl->GetName()) == 0)
167 bool DoesClassNeedConv (
const TClass*
cl,
const TBranch*
br)
169 if (!
cl)
return false;
170 TStreamerInfo*
info = GetStreamerInfoFromFile (
cl,
br);
171 if (!
info)
return false;
175 info->GetCheckSum()))
179 TObjArray* elems =
info->GetElements();
180 int ndata = elems->GetEntriesFast();
181 for (
int i = 0;
i < ndata; ++
i) {
182 TStreamerElement* elt =
183 reinterpret_cast<TStreamerElement*
> (elems->At (
i));
184 TClass* bcl = elt->GetClass();
189 if (bcl && bcl !=
cl && DoesClassNeedConv (bcl,
br))
206 bool BaseHasField1 (TStreamerBase* elt,
211 TClass*
cl = elt->GetClassPointer();
212 if (!
cl)
return false;
213 TStreamerInfo*
info = GetStreamerInfoFromFile (
cl,
br);
214 if (!
info)
return false;
218 TObjArray* elems =
info->GetElements();
219 size_t ndata = elems->GetEntriesFast();
220 for (
size_t ielt = 0; ielt < ndata; ielt++) {
221 TStreamerElement* selt =
222 reinterpret_cast<TStreamerElement*
> (elems->At(ielt));
223 if (TStreamerBase* belt =
dynamic_cast<TStreamerBase*
> (selt)) {
224 if (BaseHasField1 (belt,
name,
br))
228 if (
name == selt->GetName())
248 bool BaseHasField (TStreamerBase* elt,
250 const TString& namedot,
253 if (!elt)
return false;
254 RemovePrefix (bname, namedot.Data());
255 Ssiz_t
i = bname.Index (
"[");
258 i = bname.Index (
".");
261 return BaseHasField1 (elt, bname,
br);
265 struct R__PushCache {
266 TBufferFile &fBuffer;
267 TVirtualArray *fOnfileObject;
269 R__PushCache(TBufferFile &
b, TVirtualArray *in, UInt_t
size) : fBuffer(
b), fOnfileObject(in) {
271 fOnfileObject->SetSize(
size);
272 fBuffer.PushDataCache( fOnfileObject );
276 if (fOnfileObject) fBuffer.PopDataCache();
289 , fConvClass(nullptr)
290 , fConvObject(nullptr)
291 , fConvOrigBranches(nullptr)
293 , fConvContainerFlag(false)
294 , fConvDontReset(false)
313 Int_t nbranches = fBranches.GetEntriesFast();
314 for (Int_t
i = 0;
i < nbranches;
i++) {
386 TClass* topclass =
nullptr;
388 topclass = gROOT->GetClass (GetClassName());
390 std::string
s = BasenameOfBranch (GetName());
392 TStreamerElement* elt = fInfo->GetStreamerElement(
s.c_str(),
offset);
394 topclass = elt->GetClass();
396 if (!topclass)
return;
422 std::vector<TBranch*> conv_dummies;
423 std::vector<TBranch*> noconv_branches;
427 Int_t nbranches = fBranches.GetEntriesFast();
429 for (Int_t
i=0;
i < nbranches;
i++) {
430 TBranch*
b =
dynamic_cast<TBranchElement*
> (fBranches[
i]);
438 TStreamerInfo*
info = GetStreamerInfoFromFile (topclass,
this);
439 if (!
info && fType == 4) {
440 TVirtualCollectionProxy*
proxy = topclass->GetCollectionProxy();
442 topclass =
proxy->GetValueClass();
443 if (!topclass)
return;
444 info = GetStreamerInfoFromFile (topclass,
this);
446 else if (fType == 3) {
447 topclass = gROOT->GetClass (fClonesName);
448 if (!topclass)
return;
449 info = GetStreamerInfoFromFile (topclass,
this);
454 TObjArray* elems =
info->GetElements();
455 size_t ndata = elems->GetEntriesFast();
456 for (
size_t ielt = 0; ielt < ndata; ++ielt) {
458 TStreamerElement* elt =
459 reinterpret_cast<TStreamerElement*
> (elems->At(ielt));
465 TBranchElement*
b =
dynamic_cast<TBranchElement*
>(
branches[
i]);
468 if (
b && gROOT->GetClass (
b->GetClassName()) == topclass) {
469 if (
dynamic_cast<TStreamerBase*
> (elt) != 0 &&
b->GetType() == 1) {
475 std::string
s = BasenameOfBranch (
b->GetName());
476 if (
s == elt->GetName())
484 noconv_branches.push_back (
b);
497 TClass*
cl = elt->GetClass();
498 if (
cl && DoesClassNeedConv (
cl,
this)) {
500 TClass* clparent = gROOT->GetClass (
info->GetName());
505 name = elt->GetName();
509 Ssiz_t
i =
name.Length()-1;
510 while (
i >= 0 &&
name[
i] !=
'.')
516 name += elt->GetName();
519 dum->SetTitle (
name);
520 TString namedot =
name +
".";
521 dum->SetParentClass (clparent);
522 dum->SetClassName (
info->GetName());
523 dum->fCheckSum =
info->GetCheckSum();
524 dum->fClassVersion = topclass->GetClassVersion();
526 dum->fTree = this->fTree;
527 dum->fDirectory = this->fDirectory;
528 dum->fBranchClass = topclass;
529 if (
dynamic_cast<TStreamerBase*
> (elt) !=
nullptr) {
531 Ssiz_t
i = namedot.Length()-2;
532 while (
i >= 0 && namedot[
i] !=
'.')
534 namedot.Remove (
i+1);
540 conv_dummies.push_back (dum);
546 if (bname.Index (namedot) == 0 &&
548 BaseHasField (
dynamic_cast<TStreamerBase*
>(elt),
553 dum->GetListOfBranches()->Add (
branches[
i]);
557 be->fParentClass =
cl;
574 if (conv_dummies.size() > 0) {
584 for (
unsigned int i=0;
i < conv_dummies.size();
i++)
585 fBranches.Add (conv_dummies[
i]);
586 for (
unsigned int i=0;
i < noconv_branches.size();
i++)
587 fBranches.Add (noconv_branches[
i]);
605 const char* classname = 0;
610 classname = GetClassName();
611 checksum = fCheckSum;
615 std::string
s = BasenameOfBranch (GetName());
617 TStreamerElement* elt = fInfo->GetStreamerElement(
s.c_str(),
offset);
619 TClass*
cl = elt->GetClass();
621 classname =
cl->GetName();
622 TStreamerInfo*
info = GetStreamerInfoFromFile (
cl,
this);
624 checksum =
info->GetCheckSum();
637 if (!
conv && (fType == 4 || fType == 3)) {
639 TClass* contclass = gROOT->GetClass (fClonesName.Data());
641 TStreamerInfo*
info = GetStreamerInfoFromFile (contclass,
this);
647 info->GetCheckSum());
651 if (
conv || DoesClassNeedConv (contclass,
this)) {
660 TClass* convclass =
conv->GetPersClass();
677 TClass* convclass =
conv->GetPersClass();
683 Bool_t optim = TStreamerInfo::CanOptimize();
684 TStreamerInfo::Optimize(kFALSE);
685 TStreamerInfo*
info =
686 dynamic_cast<TStreamerInfo*
> (convclass->GetStreamerInfo (0));
689 TStreamerInfo::Optimize(optim);
690 fParentClass = convclass;
709 TBranchElement::InitInfo();
717 TBranchElement::InitInfo();
740 Int_t nbranches = fBranches.GetEntriesFast();
741 for (Int_t
i=0;
i < nbranches;
i++) {
745 if (
b->fType == 41 ||
b->fType == 31) {
746 b->fConvOrigType =
b->fType;
856 TBranchRef* bref = fTree->GetBranchRef();
858 bref->SetParent(
this, fBranchID);
859 bref->SetRequestedEntry(
entry);
866 Int_t nbranches = fBranches.GetEntriesFast();
872 if ((fType == 3) || (fType == 4)) {
873 Int_t
nb = TBranch::GetEntry(
entry, getall);
888 case TClassEdit::kSet:
889 case TClassEdit::kMultiSet:
890 case TClassEdit::kMap:
891 case TClassEdit::kMultiMap:
907 if (fBranchCount && (fBranchCount->GetReadEntry() !=
entry)) {
908 Int_t
nb = fBranchCount->TBranch::GetEntry(
entry, getall);
923 TBasket* basket = (TBasket*)GetBasket(GetReadBasket());
924 TBuffer*
buffer = basket->GetBufferRef();
925 Int_t bufbegin =
buffer->Length();
928 #if __GNUC__ >= 11 && __GNUC__ <= 14
929 # pragma GCC diagnostic push
930 # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
932 (this->*fReadLeaves) (*
buffer);
933 #if __GNUC__ >= 11 && __GNUC__ <= 14
934 # pragma GCC diagnostic pop
940 nb = TBranch::GetEntry (
entry, getall);
949 if (fTree->Debug() > 0) {
950 if ((
entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
951 Info(
"GetEntry",
"%lld, branch=%s, nbytes=%d",
entry, GetName(), nbytes);
978 if ((
n < 0) || (
n > fMaximum)) {
979 if (IsMissingCollection()) {
981 b.SetBufferOffset(
b.Length()-
sizeof(
n));
983 Error(
"ReadLeaves",
"Incorrect size read for the container in %s\n\tThe size read is %d while the maximum is %d\n\tThe size is reset to 0 for this entry (%lld)", GetName(),
n, fMaximum, GetReadEntry());
989 R__PushCache onfileObject((
static_cast<TBufferFile&
>(
b)),fOnfileObject,
n);
1001 TVirtualCollectionProxy*
proxy = GetCollectionProxy();
1002 TVirtualCollectionProxy::TPushPop
helper(
proxy, fObject);
1004 if(fSTLtype != TClassEdit::kVector &&
proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers ) {
1012 case TClassEdit::kSet:
1013 case TClassEdit::kMultiSet:
1014 case TClassEdit::kMap:
1015 case TClassEdit::kMultiMap:
1030 if(
proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers )
1032 TClass *elClass =
proxy->GetValueClass();
1039 if( !fNdata || *(
void**)
proxy->At( 0 ) != 0 )
1042 for( ;
i < fNdata; ++
i )
1044 void **
el = (
void**)
proxy->At(
i );
1046 *
el = elClass->New();
1060 assert(fStreamerType != TVirtualStreamerInfo::kCounter);
1070 R__PushCache onfileObject((
static_cast<TBufferFile&
>(
b)),fOnfileObject,1);
1075 if (TestBit(kBranchObject)) {
1077 b.MapObject((TObject*) fObject);
1078 }
else if (TestBit(kBranchAny)) {
1080 b.MapObject(fObject, fBranchClass);
1083 fNdata = (Int_t) fBranchCount->GetValue(0, 0);
1084 TStreamerInfo *
info = GetInfo();
1115 Int_t nbranches = fBranches.GetEntriesFast();
1124 UInt_t save_ndata = fNdata;
1128 TVirtualCollectionProxy*
proxy = 0;
1129 TClonesArray* clones = 0;
1131 proxy = GetCollectionProxy();
1132 else if (fType == 3)
1133 clones = (TClonesArray*)fObject;
1145 std::vector<char*> last_addrs (nbranches, (
char*)0);
1148 for (UInt_t j = 0; j < save_ndata; j++) {
1154 addr = (
char*)(
proxy->At(j));
1156 if (!clones) std::abort();
1157 addr = (
char*)((*clones)[j]);
1168 for (Int_t
i = 0;
i < nbranches; ++
i) {
1169 TBranch*
branch = (TBranch*) fBranches[
i];
1177 be->fConvDontReset =
true;
1181 char* this_addr =
obj + fBranchOffset[
i];
1184 if (this_addr != last_addrs[
i]) {
1185 last_addrs[
i] = this_addr;
1207 fNdata = save_ndata;
1214 for (Int_t
i = 0;
i < nbranches; ++
i) {
1215 TBranch*
branch = (TBranch*) fBranches[
i];
1222 be->fConvDontReset =
true;
1256 Int_t type_save = 0;
1258 if (!R__b.IsReading()) {
1270 TBranchElement::Streamer (R__b);
1272 if (!R__b.IsReading()) {
1302 TStreamerElement* branchElem = 0;
1303 TClass* cl_orig = 0;
1305 TStreamerInfo* si = GetInfo();
1306 branchElem = si->GetElem(fID);
1308 if (branchElem && branchElem->IsBase()) {
1309 cl_orig = branchElem->GetClassPointer();
1318 Int_t nbranches = fBranches.GetEntriesFast();
1319 for (Int_t subBranchIdx = 0; subBranchIdx < nbranches; ++subBranchIdx) {
1328 TBranchElement::InitializeOffsets();
1345 TBranchElement::SetAddress (
add);
1347 Int_t nbranches = fBranches.GetEntriesFast();
1348 for (Int_t
i = 0;
i < nbranches; ++
i) {
1349 TBranch* abranch = (TBranch*) fBranches[
i];
1375 char*
object = fObject;
1377 TBranchElement::ResetAddress();
1386 if (fAddress && (*((
char**) fAddress) != fObject)) {
1389 if (TestBit(kDeleteObject)) {
1390 Warning(
"ReleaseObject",
"branch: %s, You have overwritten the pointer to an object which I owned!", GetName());
1391 Warning(
"ReleaseObject",
"This is a memory leak. Please use SetAddress() to change the pointer instead.");
1392 ResetBit(kDeleteObject);
1399 if (fAddress && fObject && TestBit(kDeleteObject)) {
1400 ResetBit(kDeleteObject);
1403 TClonesArray::Class()->Destructor(fObject);
1405 if ((fStreamerType == TVirtualStreamerInfo::kObjectp) ||
1406 (fStreamerType == TVirtualStreamerInfo::kObjectP)) {
1409 *((
char**) fAddress) = 0;
1411 }
else if (fType == 4) {
1413 TVirtualCollectionProxy*
proxy = GetCollectionProxy();
1415 Warning(
"ResetAddress",
"Cannot delete allocated STL container because I do not have a proxy! branch: %s", GetName());
1418 proxy->Destructor(fObject);
1421 if (fStreamerType == TVirtualStreamerInfo::kSTLp) {
1424 *((
char**) fAddress) = 0;
1428 TClass*
cl = fBranchClass.GetClass();
1430 Warning(
"ResetAddress",
"Cannot delete allocated object because I cannot instantiate a TClass object for its class! branch: '%s' class: '%s'", GetName(), fBranchClass.GetClassName());
1433 cl->Destructor(fObject);