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;
591 if (conv_dummies.size() > 0) {
601 for (
unsigned int i=0;
i < conv_dummies.size();
i++)
602 fBranches.Add (conv_dummies[
i]);
603 for (
unsigned int i=0;
i < noconv_branches.size();
i++)
604 fBranches.Add (noconv_branches[
i]);
622 const char* classname = 0;
627 classname = GetClassName();
628 checksum = fCheckSum;
632 std::string
s = BasenameOfBranch (GetName());
634 TStreamerElement* elt = fInfo->GetStreamerElement(
s.c_str(),
offset);
636 TClass*
cl = elt->GetClass();
638 classname =
cl->GetName();
639 TStreamerInfo*
info = GetStreamerInfoFromFile (
cl,
this);
641 checksum =
info->GetCheckSum();
654 if (!
conv && (fType == 4 || fType == 3)) {
656 TClass* contclass = gROOT->GetClass (fClonesName.Data());
658 TStreamerInfo*
info = GetStreamerInfoFromFile (contclass,
this);
664 info->GetCheckSum());
668 if (
conv || DoesClassNeedConv (contclass,
this)) {
677 TClass* convclass =
conv->GetPersClass();
694 TClass* convclass =
conv->GetPersClass();
700 Bool_t optim = TStreamerInfo::CanOptimize();
701 TStreamerInfo::Optimize(kFALSE);
702 TStreamerInfo*
info =
703 dynamic_cast<TStreamerInfo*
> (convclass->GetStreamerInfo (0));
706 TStreamerInfo::Optimize(optim);
707 fParentClass = convclass;
726 TBranchElement::InitInfo();
734 TBranchElement::InitInfo();
757 Int_t nbranches = fBranches.GetEntriesFast();
758 for (Int_t
i=0;
i < nbranches;
i++) {
762 if (
b->fType == 41 ||
b->fType == 31) {
763 b->fConvOrigType =
b->fType;
873 TBranchRef* bref = fTree->GetBranchRef();
875 bref->SetParent(
this, fBranchID);
876 bref->SetRequestedEntry(
entry);
883 Int_t nbranches = fBranches.GetEntriesFast();
889 if ((fType == 3) || (fType == 4)) {
890 Int_t
nb = TBranch::GetEntry(
entry, getall);
905 case TClassEdit::kSet:
906 case TClassEdit::kMultiSet:
907 case TClassEdit::kMap:
908 case TClassEdit::kMultiMap:
924 if (fBranchCount && (fBranchCount->GetReadEntry() !=
entry)) {
925 Int_t
nb = fBranchCount->TBranch::GetEntry(
entry, getall);
940 TBasket* basket = (TBasket*)GetBasket(GetReadBasket());
941 TBuffer*
buffer = basket->GetBufferRef();
942 Int_t bufbegin =
buffer->Length();
945 #if __GNUC__ >= 11 && __GNUC__ <= 14
946 # pragma GCC diagnostic push
947 # pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
949 (this->*fReadLeaves) (*
buffer);
950 #if __GNUC__ >= 11 && __GNUC__ <= 14
951 # pragma GCC diagnostic pop
957 nb = TBranch::GetEntry (
entry, getall);
966 if (fTree->Debug() > 0) {
967 if ((
entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
968 Info(
"GetEntry",
"%lld, branch=%s, nbytes=%d",
entry, GetName(), nbytes);
995 if ((
n < 0) || (
n > fMaximum)) {
996 if (IsMissingCollection()) {
998 b.SetBufferOffset(
b.Length()-
sizeof(
n));
1000 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());
1006 R__PushCache onfileObject((
static_cast<TBufferFile&
>(
b)),fOnfileObject,
n);
1018 TVirtualCollectionProxy*
proxy = GetCollectionProxy();
1019 TVirtualCollectionProxy::TPushPop
helper(
proxy, fObject);
1021 if(fSTLtype != TClassEdit::kVector &&
proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers ) {
1029 case TClassEdit::kSet:
1030 case TClassEdit::kMultiSet:
1031 case TClassEdit::kMap:
1032 case TClassEdit::kMultiMap:
1047 if(
proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers )
1049 TClass *elClass =
proxy->GetValueClass();
1056 if( !fNdata || *(
void**)
proxy->At( 0 ) != 0 )
1059 for( ;
i < fNdata; ++
i )
1061 void **
el = (
void**)
proxy->At(
i );
1063 *
el = elClass->New();
1077 assert(fStreamerType != TVirtualStreamerInfo::kCounter);
1087 R__PushCache onfileObject((
static_cast<TBufferFile&
>(
b)),fOnfileObject,1);
1092 if (TestBit(kBranchObject)) {
1094 b.MapObject((TObject*) fObject);
1095 }
else if (TestBit(kBranchAny)) {
1097 b.MapObject(fObject, fBranchClass);
1100 fNdata = (Int_t) fBranchCount->GetValue(0, 0);
1101 TStreamerInfo *
info = GetInfo();
1132 Int_t nbranches = fBranches.GetEntriesFast();
1141 UInt_t save_ndata = fNdata;
1145 TVirtualCollectionProxy*
proxy = 0;
1146 TClonesArray* clones = 0;
1148 proxy = GetCollectionProxy();
1149 else if (fType == 3)
1150 clones = (TClonesArray*)fObject;
1162 std::vector<char*> last_addrs (nbranches, (
char*)0);
1165 for (UInt_t j = 0; j < save_ndata; j++) {
1171 addr = (
char*)(
proxy->At(j));
1173 if (!clones) std::abort();
1174 addr = (
char*)((*clones)[j]);
1185 for (Int_t
i = 0;
i < nbranches; ++
i) {
1186 TBranch*
branch = (TBranch*) fBranches[
i];
1194 be->fConvDontReset =
true;
1198 char* this_addr =
obj + fBranchOffset[
i];
1201 if (this_addr != last_addrs[
i]) {
1202 last_addrs[
i] = this_addr;
1224 fNdata = save_ndata;
1231 for (Int_t
i = 0;
i < nbranches; ++
i) {
1232 TBranch*
branch = (TBranch*) fBranches[
i];
1239 be->fConvDontReset =
true;
1273 Int_t type_save = 0;
1275 if (!R__b.IsReading()) {
1287 TBranchElement::Streamer (R__b);
1289 if (!R__b.IsReading()) {
1319 TStreamerElement* branchElem = 0;
1320 TClass* cl_orig = 0;
1322 TStreamerInfo* si = GetInfo();
1323 branchElem = si->GetElem(fID);
1325 if (branchElem && branchElem->IsBase()) {
1326 cl_orig = branchElem->GetClassPointer();
1335 Int_t nbranches = fBranches.GetEntriesFast();
1336 for (Int_t subBranchIdx = 0; subBranchIdx < nbranches; ++subBranchIdx) {
1345 TBranchElement::InitializeOffsets();
1362 TBranchElement::SetAddress (
add);
1364 Int_t nbranches = fBranches.GetEntriesFast();
1365 for (Int_t
i = 0;
i < nbranches; ++
i) {
1366 TBranch* abranch = (TBranch*) fBranches[
i];
1392 char*
object = fObject;
1394 TBranchElement::ResetAddress();
1403 if (fAddress && (*((
char**) fAddress) != fObject)) {
1406 if (TestBit(kDeleteObject)) {
1407 Warning(
"ReleaseObject",
"branch: %s, You have overwritten the pointer to an object which I owned!", GetName());
1408 Warning(
"ReleaseObject",
"This is a memory leak. Please use SetAddress() to change the pointer instead.");
1409 ResetBit(kDeleteObject);
1416 if (fAddress && fObject && TestBit(kDeleteObject)) {
1417 ResetBit(kDeleteObject);
1420 TClonesArray::Class()->Destructor(fObject);
1422 if ((fStreamerType == TVirtualStreamerInfo::kObjectp) ||
1423 (fStreamerType == TVirtualStreamerInfo::kObjectP)) {
1426 *((
char**) fAddress) = 0;
1428 }
else if (fType == 4) {
1430 TVirtualCollectionProxy*
proxy = GetCollectionProxy();
1432 Warning(
"ResetAddress",
"Cannot delete allocated STL container because I do not have a proxy! branch: %s", GetName());
1435 proxy->Destructor(fObject);
1438 if (fStreamerType == TVirtualStreamerInfo::kSTLp) {
1441 *((
char**) fAddress) = 0;
1445 TClass*
cl = fBranchClass.GetClass();
1447 Warning(
"ResetAddress",
"Cannot delete allocated object because I cannot instantiate a TClass object for its class! branch: '%s' class: '%s'", GetName(), fBranchClass.GetClassName());
1450 cl->Destructor(fObject);