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();
66inline TPushPopSafe::TPushPopSafe (TVirtualCollectionProxy* proxy,
71 fProxy->PushProxy (objectstart);
81inline TPushPopSafe::~TPushPopSafe()
96void RemovePrefix(TString& str,
const char* prefix)
98 if (
str.Length() && prefix && strlen(prefix)) {
99 if (!
str.Index(prefix)) {
100 str.Remove(0, strlen(prefix));
113std::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) {
136TStreamerInfo* 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)
167bool 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))
206bool 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())
248bool 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();
313 Int_t nbranches = fBranches.GetEntriesFast();
314 for (Int_t i = 0; i < nbranches; i++) {
315 if (fBranches[i]->TestBit (
kIsDummy))
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;
424 std::vector<TBranch*> branches;
427 Int_t nbranches = fBranches.GetEntriesFast();
428 branches.reserve (nbranches);
429 for (Int_t i=0; i < nbranches; i++) {
430 TBranch* b =
dynamic_cast<TBranchElement*
> (fBranches[i]);
432 branches.push_back (b);
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));
464 for (
unsigned i=0; i < branches.size(); i++) {
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);
485 branches.erase (branches.begin()+i);
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);
544 for (
unsigned i=0; i < branches.size(); ) {
545 TString bname = branches[i]->GetName();
546 if (bname.Index (namedot) == 0 &&
548 BaseHasField (
dynamic_cast<TStreamerBase*
>(elt),
553 dum->GetListOfBranches()->Add (branches[i]);
557 be->fParentClass = cl;
559 branches.erase (branches.begin()+i);
571 for (
unsigned int i=0; i < branches.size(); i++)
572 noconv_branches.push_back (branches[i]);
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
937 nb = buffer->Length() - bufbegin;
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);
1003 void* alternate = proxy->Allocate(fNdata,
true);
1004 if(fSTLtype != TClassEdit::kVector && proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers ) {
1005 fPtrIterators->CreateIterators(alternate, proxy);
1007 fIterators->CreateIterators(alternate, proxy);
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();
1050 proxy->Commit(alternate);
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;
1139 TPushPopSafe helper (proxy,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;
1186 branch->SetAddress (obj + fBranchOffset[i]);
1190 Int_t nb = branch->GetEntry(entry, getall);
1203 fConv->ConvertVoid (addr, obj);
1207 fNdata = save_ndata;
1214 for (Int_t i = 0; i < nbranches; ++i) {
1215 TBranch* branch = (TBranch*) fBranches[i];
1222 be->fConvDontReset =
true;
1226 Int_t nb = branch->GetEntry(entry, getall);
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];
1350 abranch->SetAddress(
fConvObject + fBranchOffset[i]);
1375 char*
object = fObject;
1376 char* address = fAddress;
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);
Registry for Root converters.
void TConvertingBranchElement_init()
To allow calling Initialize without having to depend on the header.
A variant of TBranchElement that can call converters when reading objects in split mode.
Base class for Root converters.
static TConverterRegistry * Instance()
Return a pointer to the global registry instance.
TVirtualConverter * GetConverter(const char *name, int checksum) const
Look up a converter in the registry by name and checksum.
Int_t fConvOrigType
Saved branch list. If we change.
void ReadLeavesMemberBranchCountConverting(TBuffer &b)
virtual void SetAddress(void *add)
Set the address of the object to use for I/O.
TConvertingBranchElement()
Constructor.
TVirtualConverter * fConv
bool fConvDontReset
True if we're doing a container.
virtual void ResetAddress()
Reset branch addresses and maybe delete the object.
virtual void Streamer(TBuffer &R__b)
Read or write this object.
virtual Int_t GetEntry(Long64_t entry, Int_t getall)
Read all branches into the previously-declared object.
static void SetDoDel(bool flag)
Set the deletion flag.
void ConvResetType()
Recursively reset the type field of containers in conversions.
bool fConvContainerFlag
Saved branch type. The original.
TClass * fConvClass
Conversion for this branch.
static std::atomic< bool > fgDoDel
Flag that the next read should.
static void * new_TConvertingBranchElement(void *p)
new() method for this object.
static constexpr unsigned int kIsDummy
Flag used to mark dummy nodes created by BuildConvertedElisions.
char * fConvObject
Class for conversion.
void ReadLeavesCollectionConverting(TBuffer &b)
Read leaves into I/O buffers for this branch.
virtual ~TConvertingBranchElement()
Destructor.
static void Initialize()
Set up to allow for conversions in split mode.
Int_t ReadSubBranches(Long64_t entry, Int_t getall, bool dont_reset)
@branch Read in the subbranches of this branch.
virtual void InitializeOffsets()
Initialize data member offsets.
virtual void InitInfo()
Initialize the TStreamerInfo pointer.
void CheckForConversion()
Check to see if we need to worry about conversions for this branch.
void BuildConvertedElisions()
Add dummy nodes if needed to recover the correct tree structure.
TObjArray * fConvOrigBranches
Pointer to tmp obj used for conversion.
Base class for converters for Root schema evolution.
bool add(const std::string &hname, TKey *tobj)
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]