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();
144 if (
file->GetSeekInfo() == 0)
return 0;
147 const TList* silist =
file->GetStreamerInfoCache();
148 TListIter li (silist);
150 while ((
info =
dynamic_cast<TStreamerInfo*
> (li.Next())) != 0) {
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();
291 , fConvOrigBranches(0)
293 , fConvContainerFlag(false)
294 , fConvDontReset(false)
313 Int_t nbranches = fBranches.GetEntriesFast();
314 for (Int_t
i = 0;
i < nbranches;
i++) {
338 static bool initialized =
false;
343 TClass*
cl = gROOT->GetClass (
"TBranchElement",
true);
345 ::Error (
"TConvertingBranchElement",
346 "Can't find TClass for TBranchElement");
403 TClass* topclass = 0;
405 topclass = gROOT->GetClass (GetClassName());
407 std::string
s = BasenameOfBranch (GetName());
409 TStreamerElement* elt = fInfo->GetStreamerElement(
s.c_str(),
offset);
411 topclass = elt->GetClass();
413 if (!topclass)
return;
439 std::vector<TBranch*> conv_dummies;
440 std::vector<TBranch*> noconv_branches;
444 Int_t nbranches = fBranches.GetEntriesFast();
446 for (Int_t
i=0;
i < nbranches;
i++) {
447 TBranch*
b =
dynamic_cast<TBranchElement*
> (fBranches[
i]);
455 TStreamerInfo*
info = GetStreamerInfoFromFile (topclass,
this);
456 if (!
info && fType == 4) {
457 TVirtualCollectionProxy*
proxy = topclass->GetCollectionProxy();
459 topclass =
proxy->GetValueClass();
460 if (!topclass)
return;
461 info = GetStreamerInfoFromFile (topclass,
this);
463 else if (fType == 3) {
464 topclass = gROOT->GetClass (fClonesName);
465 if (!topclass)
return;
466 info = GetStreamerInfoFromFile (topclass,
this);
471 TObjArray* elems =
info->GetElements();
472 size_t ndata = elems->GetEntriesFast();
473 for (
size_t ielt = 0; ielt < ndata; ++ielt) {
475 TStreamerElement* elt =
476 reinterpret_cast<TStreamerElement*
> (elems->At(ielt));
482 TBranchElement*
b =
dynamic_cast<TBranchElement*
>(
branches[
i]);
485 if (
b && gROOT->GetClass (
b->GetClassName()) == topclass) {
486 if (
dynamic_cast<TStreamerBase*
> (elt) != 0 &&
b->GetType() == 1) {
492 std::string
s = BasenameOfBranch (
b->GetName());
493 if (
s == elt->GetName())
501 noconv_branches.push_back (
b);
514 TClass*
cl = elt->GetClass();
515 if (
cl && DoesClassNeedConv (
cl,
this)) {
517 TClass* clparent = gROOT->GetClass (
info->GetName());
522 name = elt->GetName();
526 Ssiz_t
i =
name.Length()-1;
527 while (
i >= 0 &&
name[
i] !=
'.')
533 name += elt->GetName();
536 dum->SetTitle (
name);
537 TString namedot =
name +
".";
538 dum->SetParentClass (clparent);
539 dum->SetClassName (
info->GetName());
540 dum->fCheckSum =
info->GetCheckSum();
541 dum->fClassVersion = topclass->GetClassVersion();
543 dum->fTree = this->fTree;
544 dum->fDirectory = this->fDirectory;
545 dum->fBranchClass = topclass;
546 if (
dynamic_cast<TStreamerBase*
> (elt) != 0) {
548 Ssiz_t
i = namedot.Length()-2;
549 while (
i >= 0 && namedot[
i] !=
'.')
551 namedot.Remove (
i+1);
557 conv_dummies.push_back (dum);
563 if (bname.Index (namedot) == 0 &&
565 BaseHasField (
dynamic_cast<TStreamerBase*
>(elt),
570 dum->GetListOfBranches()->Add (
branches[
i]);
574 be->fParentClass =
cl;
589 if (conv_dummies.size() > 0) {
599 for (
unsigned int i=0;
i < conv_dummies.size();
i++)
600 fBranches.Add (conv_dummies[
i]);
601 for (
unsigned int i=0;
i < noconv_branches.size();
i++)
602 fBranches.Add (noconv_branches[
i]);
620 const char* classname = 0;
625 classname = GetClassName();
626 checksum = fCheckSum;
630 std::string
s = BasenameOfBranch (GetName());
632 TStreamerElement* elt = fInfo->GetStreamerElement(
s.c_str(),
offset);
634 TClass*
cl = elt->GetClass();
636 classname =
cl->GetName();
637 TStreamerInfo*
info = GetStreamerInfoFromFile (
cl,
this);
639 checksum =
info->GetCheckSum();
652 if (!
conv && (fType == 4 || fType == 3)) {
654 TClass* contclass = gROOT->GetClass (fClonesName.Data());
656 TStreamerInfo*
info = GetStreamerInfoFromFile (contclass,
this);
662 info->GetCheckSum());
666 if (
conv || DoesClassNeedConv (contclass,
this)) {
675 TClass* convclass =
conv->GetPersClass();
692 TClass* convclass =
conv->GetPersClass();
698 Bool_t optim = TStreamerInfo::CanOptimize();
699 TStreamerInfo::Optimize(kFALSE);
700 TStreamerInfo*
info =
701 dynamic_cast<TStreamerInfo*
> (convclass->GetStreamerInfo (0));
704 TStreamerInfo::Optimize(optim);
705 fParentClass = convclass;
724 TBranchElement::InitInfo();
732 TBranchElement::InitInfo();
755 Int_t nbranches = fBranches.GetEntriesFast();
756 for (Int_t
i=0;
i < nbranches;
i++) {
760 if (
b->fType == 41 ||
b->fType == 31) {
761 b->fConvOrigType =
b->fType;
871 TBranchRef* bref = fTree->GetBranchRef();
873 bref->SetParent(
this, fBranchID);
874 bref->SetRequestedEntry(
entry);
881 Int_t nbranches = fBranches.GetEntriesFast();
887 if ((fType == 3) || (fType == 4)) {
888 Int_t
nb = TBranch::GetEntry(
entry, getall);
903 case TClassEdit::kSet:
904 case TClassEdit::kMultiSet:
905 case TClassEdit::kMap:
906 case TClassEdit::kMultiMap:
922 if (fBranchCount && (fBranchCount->GetReadEntry() !=
entry)) {
923 Int_t
nb = fBranchCount->TBranch::GetEntry(
entry, getall);
938 TBasket* basket = (TBasket*)GetBasket(GetReadBasket());
939 TBuffer*
buffer = basket->GetBufferRef();
940 Int_t bufbegin =
buffer->Length();
943 #if __GNUC__ >= 11 && __GNUC__ <= 13
944 # pragma GCC diagnostic push
945 # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
947 (this->*fReadLeaves) (*
buffer);
948 #if __GNUC__ >= 11 && __GNUC__ <= 13
949 # pragma GCC diagnostic pop
955 nb = TBranch::GetEntry (
entry, getall);
964 if (fTree->Debug() > 0) {
965 if ((
entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
966 Info(
"GetEntry",
"%lld, branch=%s, nbytes=%d",
entry, GetName(), nbytes);
993 if ((
n < 0) || (
n > fMaximum)) {
994 if (IsMissingCollection()) {
996 b.SetBufferOffset(
b.Length()-
sizeof(
n));
998 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());
1004 R__PushCache onfileObject(((TBufferFile&)
b),fOnfileObject,
n);
1016 TVirtualCollectionProxy*
proxy = GetCollectionProxy();
1017 TVirtualCollectionProxy::TPushPop
helper(
proxy, fObject);
1019 if(fSTLtype != TClassEdit::kVector &&
proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers ) {
1027 case TClassEdit::kSet:
1028 case TClassEdit::kMultiSet:
1029 case TClassEdit::kMap:
1030 case TClassEdit::kMultiMap:
1045 if(
proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers )
1047 TClass *elClass =
proxy->GetValueClass();
1054 if( !fNdata || *(
void**)
proxy->At( 0 ) != 0 )
1057 for( ;
i < fNdata; ++
i )
1059 void **
el = (
void**)
proxy->At(
i );
1061 *
el = elClass->New();
1075 assert(fStreamerType != TVirtualStreamerInfo::kCounter);
1085 R__PushCache onfileObject(((TBufferFile&)
b),fOnfileObject,1);
1090 if (TestBit(kBranchObject)) {
1092 b.MapObject((TObject*) fObject);
1093 }
else if (TestBit(kBranchAny)) {
1095 b.MapObject(fObject, fBranchClass);
1098 fNdata = (Int_t) fBranchCount->GetValue(0, 0);
1099 TStreamerInfo *
info = GetInfo();
1130 Int_t nbranches = fBranches.GetEntriesFast();
1139 UInt_t save_ndata = fNdata;
1143 TVirtualCollectionProxy*
proxy = 0;
1144 TClonesArray* clones = 0;
1146 proxy = GetCollectionProxy();
1147 else if (fType == 3)
1148 clones = (TClonesArray*)fObject;
1160 std::vector<char*> last_addrs (nbranches, (
char*)0);
1163 for (UInt_t j = 0; j < save_ndata; j++) {
1169 addr = (
char*)(
proxy->At(j));
1171 if (!clones) std::abort();
1172 addr = (
char*)((*clones)[j]);
1183 for (Int_t
i = 0;
i < nbranches; ++
i) {
1184 TBranch*
branch = (TBranch*) fBranches[
i];
1192 be->fConvDontReset =
true;
1196 char* this_addr =
obj + fBranchOffset[
i];
1199 if (this_addr != last_addrs[
i]) {
1200 last_addrs[
i] = this_addr;
1222 fNdata = save_ndata;
1229 for (Int_t
i = 0;
i < nbranches; ++
i) {
1230 TBranch*
branch = (TBranch*) fBranches[
i];
1237 be->fConvDontReset =
true;
1271 Int_t type_save = 0;
1273 if (!R__b.IsReading()) {
1285 TBranchElement::Streamer (R__b);
1287 if (!R__b.IsReading()) {
1317 TStreamerElement* branchElem = 0;
1318 TClass* cl_orig = 0;
1320 TStreamerInfo* si = GetInfo();
1321 branchElem = si->GetElem(fID);
1323 if (branchElem && branchElem->IsBase()) {
1324 cl_orig = branchElem->GetClassPointer();
1333 Int_t nbranches = fBranches.GetEntriesFast();
1334 for (Int_t subBranchIdx = 0; subBranchIdx < nbranches; ++subBranchIdx) {
1343 TBranchElement::InitializeOffsets();
1360 TBranchElement::SetAddress (
add);
1362 Int_t nbranches = fBranches.GetEntriesFast();
1363 for (Int_t
i = 0;
i < nbranches; ++
i) {
1364 TBranch* abranch = (TBranch*) fBranches[
i];
1390 char*
object = fObject;
1392 TBranchElement::ResetAddress();
1401 if (fAddress && (*((
char**) fAddress) != fObject)) {
1404 if (TestBit(kDeleteObject)) {
1405 Warning(
"ReleaseObject",
"branch: %s, You have overwritten the pointer to an object which I owned!", GetName());
1406 Warning(
"ReleaseObject",
"This is a memory leak. Please use SetAddress() to change the pointer instead.");
1407 ResetBit(kDeleteObject);
1414 if (fAddress && fObject && TestBit(kDeleteObject)) {
1415 ResetBit(kDeleteObject);
1418 TClonesArray::Class()->Destructor(fObject);
1420 if ((fStreamerType == TVirtualStreamerInfo::kObjectp) ||
1421 (fStreamerType == TVirtualStreamerInfo::kObjectP)) {
1424 *((
char**) fAddress) = 0;
1426 }
else if (fType == 4) {
1428 TVirtualCollectionProxy*
proxy = GetCollectionProxy();
1430 Warning(
"ResetAddress",
"Cannot delete allocated STL container because I do not have a proxy! branch: %s", GetName());
1433 proxy->Destructor(fObject);
1436 if (fStreamerType == TVirtualStreamerInfo::kSTLp) {
1439 *((
char**) fAddress) = 0;
1443 TClass*
cl = fBranchClass.GetClass();
1445 Warning(
"ResetAddress",
"Cannot delete allocated object because I cannot instantiate a TClass object for its class! branch: '%s' class: '%s'", GetName(), fBranchClass.GetClassName());
1448 cl->Destructor(fObject);