Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TBranchElement.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id$
2// Authors Rene Brun , Philippe Canal, Markus Frank 14/01/2001
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TBranchElement
13\ingroup tree
14
15A Branch for the case of an object.
16*/
17
18#include "TBranchElement.h"
19
20#include "TBasket.h"
21#include "TBranchObject.h"
22#include "TBranchRef.h"
23#include "TBrowser.h"
24#include "TClass.h"
25#include "TClassEdit.h"
26#include "TClonesArray.h"
27#include "TDataMember.h"
28#include "TDataType.h"
29#include "TError.h"
30#include "TMath.h"
31#include "TFile.h"
32#include "TFolder.h"
33#include "TLeafElement.h"
34#include "TRealData.h"
35#include "TStreamerElement.h"
36#include "TStreamerInfo.h"
37#include "TTree.h"
40#include "TVirtualMutex.h"
41#include "TVirtualPad.h"
42#include "TBranchSTL.h"
43#include "TVirtualArray.h"
44#include "TBufferFile.h"
45#include "TInterpreter.h"
46#include "TROOT.h"
47
49#include "TSchemaRuleSet.h"
50
52
53////////////////////////////////////////////////////////////////////////////////
54
55namespace {
56 void RemovePrefix(TString& str, const TString &prefix) {
57 // -- Remove a prefix from a string.
58 // -- Require a '.' after the prefix.
59 if (prefix.Length() && prefix.Length() <= str.Length()
60 && (str.Data()[prefix.Length()] == '.' || (prefix[prefix.Length()-1]=='.')))
61 {
62 if (!str.Index(prefix))
63 str.Remove(0, prefix.Length());
64 }
65 }
66 struct R__PushCache {
68 TVirtualArray *fOnfileObject;
69
70 R__PushCache(TBuffer &b, TVirtualArray *in, UInt_t size) : fBuffer(b), fOnfileObject(in)
71 {
72 if (fOnfileObject) {
73 fOnfileObject->SetSize(size);
74 fBuffer.PushDataCache( fOnfileObject );
75 }
76 }
78 if (fOnfileObject) fBuffer.PopDataCache();
79 }
80 };
81 ////////////////////////////////////////////////////////////////////////////////
82 /// Check if a collection proxy represents an associative collection (e.g., std::map, std::set)
83 /// rather than a sequential collection (e.g., std::vector, std::list).
84 /// Both the version based on the fSTLtype integer and the one based on the TVirtualCollectionProxy
85 /// will return the same result about the 'currently' in memory collection attached to the branch.
86 /// The main difference is that the fSTLtype can be used without checking whether
87 /// fCollProxy is set or not but might (or might not) be a tad bit slower.
89 {
90 switch (stltype) {
91 case ROOT::kSTLset:
95 case ROOT::kSTLmap:
99 return true;
100 default:
101 return false;
102 }
103 }
105 {
106 return proxy.GetProperties() & TVirtualCollectionProxy::kIsAssociative;
107 }
108
110 {
111 br->ResetReadEntry();
112 for (auto sub : *br->GetListOfBranches())
114 }
115}
116
117////////////////////////////////////////////////////////////////////////////////
118/// Modify the container type of the branches
119
121 const Int_t nbranches = branches->GetEntriesFast();
122 for (Int_t i = 0; i < nbranches; ++i) {
123 TBranchElement* br = static_cast<TBranchElement*>(branches->At(i));
124 switch (br->GetType()) {
125 case 31: br->SetType(41); break;
126 case 41: {
127 br->SetType(31);
128 br->fCollProxy = nullptr;
129 break;
130 }
131 }
132 br->SetReadLeavesPtr();
133 br->SetFillLeavesPtr();
134 // Note: This is a tail recursion.
135 SwitchContainer(br->GetListOfBranches());
136 }
137}
138
139////////////////////////////////////////////////////////////////////////////////
140
141namespace {
142 bool CanSelfReference(TClass *cl) {
143 if (cl) {
144 if (cl->GetCollectionProxy()) {
145 TClass *inside = cl->GetCollectionProxy()->GetValueClass();
146 if (inside) {
147 return CanSelfReference(inside);
148 } else {
149 return false;
150 }
151 }
152 const static TClassRef stringClass("std::string");
153 if (cl == stringClass || cl == TString::Class()) {
154 return false;
155 }
156 // Here we could scan through the TStreamerInfo to see if there
157 // is any pointer anywhere and know whether this is a possibility
158 // of selfreference (but watch out for very indirect cases).
159 return true;
160 }
161 return false;
162 }
163}
164
165////////////////////////////////////////////////////////////////////////////////
166/// Default and I/O constructor.
167
169: TBranch()
170, fClassName()
171, fParentName()
172, fClonesName()
173, fCollProxy(nullptr)
174, fCheckSum(0)
175, fClassVersion(0)
176, fID(0)
177, fType(0)
178, fStreamerType(-1)
179, fMaximum(0)
180, fSTLtype(ROOT::kNotSTL)
181, fNdata(1)
182, fBranchCount(nullptr)
183, fBranchCount2(nullptr)
184, fInfo(nullptr)
185, fObject(nullptr)
186, fOnfileObject(nullptr)
187, fInit(false)
188, fInInitInfo(false)
189, fInitOffsets(false)
190, fTargetClass()
191, fCurrentClass()
192, fParentClass()
193, fBranchClass()
194, fClonesClass()
195, fBranchOffset(nullptr)
196, fBranchID(-1)
197, fReadActionSequence(nullptr)
198, fFillActionSequence(nullptr)
199, fIterators(nullptr)
200, fWriteIterators(nullptr)
201, fPtrIterators(nullptr)
202{
203 fNleaves = 0;
206}
207
208////////////////////////////////////////////////////////////////////////////////
209/// Constructor when the branch object is not a TClonesArray nor an STL container.
210///
211/// If splitlevel > 0 this branch in turn is split into sub-branches.
212
213TBranchElement::TBranchElement(TTree *tree, const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
214: TBranch()
215, fClassName(sinfo->GetName())
216, fParentName()
217, fClonesName()
218, fCollProxy(nullptr)
219, fCheckSum(sinfo->GetCheckSum())
220, fClassVersion(sinfo->GetClass()->GetClassVersion())
221, fID(id)
222, fType(0)
223, fStreamerType(-1)
224, fMaximum(0)
225, fSTLtype(ROOT::kNotSTL)
226, fNdata(1)
227, fBranchCount(nullptr)
228, fBranchCount2(nullptr)
229, fInfo(sinfo)
230, fObject(nullptr)
231, fOnfileObject(nullptr)
232, fInit(true)
233, fInInitInfo(false)
234, fInitOffsets(false)
235, fTargetClass(fClassName)
236, fCurrentClass()
237, fParentClass()
238, fBranchClass(sinfo->GetClass())
239, fClonesClass()
240, fBranchOffset(nullptr)
241, fBranchID(-1)
242, fReadActionSequence(nullptr)
243, fFillActionSequence(nullptr)
244, fIterators(nullptr)
245, fWriteIterators(nullptr)
246, fPtrIterators(nullptr)
247{
248 if (tree) {
249 ROOT::TIOFeatures features = tree->GetIOFeatures();
251 }
252 Init(tree, nullptr, bname,sinfo,id,pointer,basketsize,splitlevel,btype);
253}
254
255////////////////////////////////////////////////////////////////////////////////
256/// Constructor when the branch object is not a TClonesArray nor an STL container.
257///
258/// If splitlevel > 0 this branch in turn is split into sub-branches.
259
260TBranchElement::TBranchElement(TBranch *parent, const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
261: TBranch()
262, fClassName(sinfo->GetName())
263, fParentName()
264, fClonesName()
265, fCollProxy(nullptr)
266, fCheckSum(sinfo->GetCheckSum())
267, fClassVersion(sinfo->GetClass()->GetClassVersion())
268, fID(id)
269, fType(0)
270, fStreamerType(-1)
271, fMaximum(0)
272, fSTLtype(ROOT::kNotSTL)
273, fNdata(1)
274, fBranchCount(nullptr)
275, fBranchCount2(nullptr)
276, fInfo(sinfo)
277, fObject(nullptr)
278, fOnfileObject(nullptr)
279, fInit(true)
280, fInInitInfo(false)
281, fInitOffsets(false)
282, fTargetClass( fClassName )
283, fCurrentClass()
284, fParentClass()
285, fBranchClass(sinfo->GetClass())
286, fClonesClass()
287, fBranchOffset(nullptr)
288, fBranchID(-1)
289, fReadActionSequence(nullptr)
290, fFillActionSequence(nullptr)
291, fIterators(nullptr)
292, fWriteIterators(nullptr)
293, fPtrIterators(nullptr)
294{
297 Init(parent ? parent->GetTree() : nullptr, parent, bname,sinfo,id,pointer,basketsize,splitlevel,btype);
298}
299
300////////////////////////////////////////////////////////////////////////////////
301/// Init when the branch object is not a TClonesArray nor an STL container.
302///
303/// If splitlevel > 0 this branch in turn is split into sub-branches.
304
305void TBranchElement::Init(TTree *tree, TBranch *parent,const char* bname, TStreamerInfo* sinfo, Int_t id, char* pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
306{
307 TString name(bname);
308
309 // Set our TNamed attributes.
310 SetName(name);
311 SetTitle(name);
312
313 // Set our TBranch attributes.
315 fTree = tree;
316 if (fTree == nullptr) return;
317 fMother = parent ? parent->GetMother() : this;
318 fParent = parent;
320 fFileName = "";
321
322 // Clear the bit kAutoDelete to specify that when reading
323 // the object should not be deleted before calling Streamer.
324
325 SetAutoDelete(false);
326
329
330 //---------------------------------------------------------------------------
331 // Handling the splitting of the STL collections of pointers
332 /////////////////////////////////////////////////////////////////////////////
333
336
337 fCompress = -1;
338 if (fTree->GetDirectory()) {
340 if (bfile) {
341 fCompress = bfile->GetCompressionSettings();
342 }
343 }
344
345 //
346 // Initialize streamer type and element.
347 //
348
349 if (id > -1) {
350 // We are *not* a top-level branch.
351 TStreamerElement* element = sinfo->GetElement(id);
352 fStreamerType = element->GetType();
353 }
354
355 //
356 // Handle varying-length datatypes by allocating an offsets array.
357 //
358 // The fBits part of a TObject is of varying length because the pidf
359 // is streamed only when the TObject is referenced by a TRef.
360 //
361
362 fEntryOffsetLen = 0;
365 }
366
367 //
368 // Make sure the basket is big enough to contain the
369 // entry offset array plus 100 bytes of data.
370 //
371
372 if (basketsize < (100 + fEntryOffsetLen)) {
374 }
376
377 //
378 // Allocate and initialize the basket control arrays.
379 //
380
384
385 for (Int_t i = 0; i < fMaxBaskets; ++i) {
386 fBasketBytes[i] = 0;
387 fBasketEntry[i] = 0;
388 fBasketSeek[i] = 0;
389 }
390
391 // We need to keep track of the counter branch if we have
392 // one, since we cannot set it until we have created our
393 // leaf, which we do last.
394 TBranchElement* brOfCounter = nullptr;
395
396 if (id < 0) {
397 // -- We are a top-level branch. Don't split a top-level branch, TTree::Bronch will do that work.
398 if (fBranchClass.GetClass()) {
399 bool hasCustomStreamer = false;
404 } else {
407 }
408 if (hasCustomStreamer) {
409 fType = -1;
410 }
411 }
412 } else {
413 // -- We are a sub-branch of a split object.
414 TStreamerElement* element = sinfo->GetElement(id);
416 // -- If we are an object data member which inherits from TObject,
417 // flag it so that later during i/o we will register the object
418 // with the buffer so that pointers are handled correctly.
422 } else {
424 }
425 }
426 }
427 if (element->IsA() == TStreamerBasicPointer::Class()) {
428 // -- Fixup title with counter if we are a varying length array data member.
431 countname = bname;
432 Ssiz_t dot = countname.Last('.');
433 if (dot>=0) {
434 countname.Remove(dot+1);
435 } else {
436 countname = "";
437 }
438 countname += bp->GetCountName();
440 countname.Form("%s[%s]",name.Data(),bp->GetCountName());
442
443 } else if (element->IsA() == TStreamerLoop::Class()) {
444 // -- Fixup title with counter if we are a varying length array data member.
445 TStreamerLoop *bp = static_cast<TStreamerLoop *>(element);
447 countname = bname;
448 Ssiz_t dot = countname.Last('.');
449 if (dot>=0) {
450 countname.Remove(dot+1);
451 } else {
452 countname = "";
453 }
454 countname += bp->GetCountName();
456 countname.Form("%s[%s]",name.Data(),bp->GetCountName());
458
459 }
460
461 if (splitlevel > 0) {
462 // -- Create sub branches if requested by splitlevel.
463 const char* elemType = element->GetTypeName();
464 TClass *elementClass = element->GetClassPointer();
465 fSTLtype = elementClass ? elementClass->GetCollectionType() : ROOT::kNotSTL;
466 if (element->CannotSplit()) {
467 fSplitLevel = 0;
468 } else if (element->IsA() == TStreamerBase::Class()) {
469 // -- We are a base class element.
470 // Note: This does not include an STL container class which is
471 // being used as a base class because the streamer element
472 // in that case is not the base streamer element it is the
473 // STL streamer element.
474 fType = 1;
475 TClass* clOfElement = element->GetClassPointer();
477 // Note: The following code results in base class branches
478 // having two different cases for what their parent
479 // class will be, this is very annoying. It is also
480 // very annoying that the naming conventions for the
481 // sub-branch names are different as well.
482 if (!strcmp(name, clOfElement->GetName())) {
483 // -- If the branch's name is the same as the base class name,
484 // which happens when we are a child branch of a top-level
485 // branch whose name does not end in a dot and also has no
486 // internal dots, elide the branch name, and keep the branch
487 // hierarchy rooted at the ultimate parent, this keeps the base
488 // class part of the branch name from propagating downwards.
489 // FIXME: We are eliding the base class here, creating a break in the branch hierarchy.
490 // Note: We can use parent class (cltop) != branch class (elemClass) to detection elision.
494 return;
495 }
496 // If the branch's name is not the same as the base class name,
497 // keep the branch name as a prefix (i.e., continue the branch
498 // hierarchy), but start a new class hierarchy at the base class.
499 //
500 // Note: If the parent branch was created by the branch constructor
501 // which takes a folder as a parameter, then this case will
502 // be used, because the branch name will be the same as the
503 // parent branch name.
504 // Note: This means that the sub-branches of a base class branch
505 // created by TTree::Bronch() have the base class name as
506 // as part of the branch name, while those created by
507 // Unroll() do not, ouch!!!
508 //
510 if (strchr(bname, '.')) {
511 // Note: How can this happen?
512 // Answer: This is the case when using the new branch
513 // naming convention where the top-level branch ends in dot.
514 // Note: Well actually not entirely, we could also be a sub-branch
515 // of a split class, even when the top-level branch does not
516 // end in a dot.
517 // Note: Or the top-level branch could have been created by the
518 // branch constructor which takes a folder as input, in which
519 // case the top-level branch name will have internal dots
520 // representing the folder hierarchy.
523 return;
524 }
526 // -- We did not add any branches in the Unroll, finalize our name to be the base class name, because Unroll did not do it for us.
527 const auto bnamelen = strlen(bname);
528 if (bnamelen) {
529 name.Form("%s%s%s", bname, bname[bnamelen-1]=='.' ? "" : ".", clOfElement->GetName());
530 } else {
531 name.Form("%s", clOfElement->GetName());
532 }
533 SetName(name);
534 SetTitle(name);
535 }
538 return;
539 } else if (element->GetClassPointer() == TClonesArray::Class()) {
540 // -- We are a TClonesArray element.
541 bool ispointer = element->IsaPointer();
543 if (ispointer) {
544 char **ppointer = reinterpret_cast<char**>(pointer);
545 clones = reinterpret_cast<TClonesArray*>(*ppointer);
546 } else {
547 clones = reinterpret_cast<TClonesArray*>(pointer);
548 }
549 // basket->DeleteEntryOffset(); //entryoffset not required for the clonesarray counter
550 fEntryOffsetLen = 0;
551 // ===> Create a leafcount
553 fNleaves = 1;
555 fTree->GetListOfLeaves()->Add(leaf);
556 if (!clones) {
558 return;
559 }
560 TClass* clOfClones = clones->GetClass();
561 if (!clOfClones) {
564 return;
565 }
566 fType = 3;
567 // ===> create sub branches for each data member of a TClonesArray
568 //check that the contained objects class name is part of the element title
569 //This name is mandatory when reading the Tree later on and
570 //the parent class with the pointer to the TClonesArray is not available.
571 fClonesName = clOfClones->GetName();
574 aname.Form(" (%s)", clOfClones->GetName());
575 TString atitle = element->GetTitle();
576 if (!atitle.Contains(aname)) {
577 atitle += aname;
578 element->SetTitle(atitle.Data());
579 }
581 if (branchname.EndsWith("."))
582 branchname.Remove(branchname.Length()-1);
583 branchname += "_";
585 leaf->SetName(branchname);
586 leaf->SetTitle(branchname);
587 leaf->SetRange(true);
592 return;
594 // -- We are an STL container element.
596 fCollProxy = contCl->GetCollectionProxy()->Generate();
598 // Check to see if we can split the container.
599 bool cansplit = true;
600 if (!valueClass) {
601 cansplit = false;
602 } else if ((valueClass == TString::Class()) || (valueClass == TClass::GetClass("string"))) {
603 cansplit = false;
604 } else if (GetCollectionProxy()->HasPointers() && !splitSTLP ) {
605 cansplit = false;
606 } else if (!valueClass->CanSplit() && !(GetCollectionProxy()->HasPointers() && splitSTLP)) {
607 cansplit = false;
608 } else if (valueClass->GetCollectionProxy()) {
609 // -- A collection was stored in a collection, we choose not to split it.
610 // Note: Splitting it would require extending TTreeFormula
611 // to understand how to access it.
612 cansplit = false;
613 }
614 if (cansplit) {
615 // -- Do the splitting work if we are allowed to.
616 fType = 4;
617 // Create a leaf for the master branch (the counter).
619 fNleaves = 1;
621 fTree->GetListOfLeaves()->Add(leaf);
622 // Check that the contained objects class name is part of the element title.
623 // This name is mandatory when reading the tree later on and
624 // the parent class with the pointer to the STL container is not available.
625 fClonesName = valueClass->GetName();
628 aname.Form(" (%s)", valueClass->GetName());
629 TString atitle = element->GetTitle();
630 if (!atitle.Contains(aname)) {
631 atitle += aname;
632 element->SetTitle(atitle.Data());
633 }
635 if (branchname.EndsWith("."))
636 branchname.Remove(branchname.Length()-1);
637 branchname += "_";
639 leaf->SetName(branchname);
640 leaf->SetTitle(branchname);
641 leaf->SetRange(true);
642 // Create sub branches for each data member of an STL container.
647 return;
648 }
650 // -- Create sub-branches for members that are classes.
651 //
652 // Note: This can only happen if we were called directly
653 // (usually by TClass::Bronch) because Unroll never
654 // calls us for an element of this type.
655 fType = 2;
657 Int_t err = Unroll(name, clm, clm, pointer, basketsize, splitlevel+splitSTLP, 0);
658 if (err >= 0) {
659 // Return on success.
660 // FIXME: Why not on error too?
663 return;
664 }
665 }
666 }
667 }
668
669 //
670 // Create a leaf to represent this branch.
671 //
672
674 leaf->SetTitle(GetTitle());
675 fNleaves = 1;
677 fTree->GetListOfLeaves()->Add(leaf);
678
679 //
680 // If we have a counter branch set it now that we have
681 // created our leaf, we cannot do it before then.
682 //
683
684 if (brOfCounter) {
686 }
687
690}
691
692////////////////////////////////////////////////////////////////////////////////
693/// Constructor when the branch object is a TClonesArray.
694///
695/// If splitlevel > 0 this branch in turn is split into sub branches.
696
698: TBranch()
699, fClassName("TClonesArray")
700, fParentName()
701, fInfo(static_cast<TStreamerInfo*>(TClonesArray::Class()->GetStreamerInfo()))
702, fInit(true)
703, fInInitInfo(false)
704, fInitOffsets(false)
705, fTargetClass( fClassName )
706, fCurrentClass()
707, fParentClass()
708, fBranchClass(TClonesArray::Class())
709, fBranchID(-1)
710, fReadActionSequence(nullptr)
711, fFillActionSequence(nullptr)
712, fIterators(nullptr)
713, fWriteIterators(nullptr)
714, fPtrIterators(nullptr)
715{
716 Init(tree, nullptr, bname, clones, basketsize, splitlevel, compress);
717}
718
719////////////////////////////////////////////////////////////////////////////////
720/// Constructor when the branch object is a TClonesArray.
721///
722/// If splitlevel > 0 this branch in turn is split into sub branches.
723
725: TBranch()
726, fClassName("TClonesArray")
727, fParentName()
728, fInfo(static_cast<TStreamerInfo*>(TClonesArray::Class()->GetStreamerInfo()))
729, fInit(true)
730, fInInitInfo(false)
731, fInitOffsets(false)
732, fTargetClass( fClassName )
733, fCurrentClass()
734, fParentClass()
735, fBranchClass(TClonesArray::Class())
736, fBranchID(-1)
737, fReadActionSequence(nullptr)
738, fFillActionSequence(nullptr)
739, fIterators(nullptr)
740, fWriteIterators(nullptr)
741, fPtrIterators(nullptr)
742{
743 Init(parent ? parent->GetTree() : nullptr, parent, bname, clones, basketsize, splitlevel, compress);
744}
745
746////////////////////////////////////////////////////////////////////////////////
747/// Init when the branch object is a TClonesArray.
748///
749/// If splitlevel > 0 this branch in turn is split into sub branches.
750
752{
753 fCollProxy = nullptr;
755 fID = 0;
756 fInit = true;
757 fStreamerType = -1;
758 fType = 0;
759 fClassVersion = TClonesArray::Class()->GetClassVersion();
761 fBranchCount = nullptr;
762 fBranchCount2 = nullptr;
763 fObject = nullptr;
764 fOnfileObject = nullptr;
765 fMaximum = 0;
766 fBranchOffset = nullptr;
768 fInitOffsets = false;
769
770 fTree = tree;
771 fMother = parent ? parent->GetMother() : this;
772 fParent = parent;
774 fFileName = "";
775
776 SetName(bname);
777 const char* name = GetName();
778
779 SetTitle(name);
780 //fClassName = fInfo->GetName();
782 if (compress == -1 && fTree->GetDirectory()) {
784 if (bfile) fCompress = bfile->GetCompressionSettings();
785 }
786
787 if (basketsize < 100) basketsize = 100;
792
793 for (Int_t i=0;i<fMaxBaskets;i++) {
794 fBasketBytes[i] = 0;
795 fBasketEntry[i] = 0;
796 fBasketSeek[i] = 0;
797 }
798
799 // Reset the bit kAutoDelete to specify that when reading
800 // the object should not be deleted before calling the streamer.
801 SetAutoDelete(false);
802
803 // create sub branches if requested by splitlevel
805 TClass* clonesClass = clones->GetClass();
806 if (!clonesClass) {
807 Error("Init","Missing class object of the TClonesArray %s\n",clones->GetName());
808 return;
809 }
810 fType = 3;
811 // ===> Create a leafcount
813 fNleaves = 1;
815 fTree->GetListOfLeaves()->Add(leaf);
816 // ===> create sub branches for each data member of a TClonesArray
817 fClonesName = clonesClass->GetName();
820 if (branchname[branchname.Length()-1]=='.') {
821 branchname.Remove(branchname.Length()-1);
822 }
823 branchname += "_";
825 leaf->SetName(branchname);
826 leaf->SetTitle(branchname);
831 return;
832 }
833
834 if (!clones->GetClass() || CanSelfReference(clones->GetClass())) {
836 }
838 leaf->SetTitle(GetTitle());
839 fNleaves = 1;
841 fTree->GetListOfLeaves()->Add(leaf);
842
845}
846
847////////////////////////////////////////////////////////////////////////////////
848/// Constructor when the branch object is an STL collection.
849///
850/// If splitlevel > 0 this branch in turn is split into sub branches.
851
853: TBranch()
854, fClassName(cont->GetCollectionClass()->GetName())
855, fParentName()
856, fInit(true)
857, fInInitInfo(false)
858, fInitOffsets(false)
859, fTargetClass( fClassName )
860, fCurrentClass()
861, fParentClass()
862, fBranchClass(cont->GetCollectionClass())
863, fBranchID(-1)
864, fReadActionSequence(nullptr)
865, fFillActionSequence(nullptr)
866, fIterators(nullptr)
867, fWriteIterators(nullptr)
868, fPtrIterators(nullptr)
869{
870 Init(tree, nullptr, bname, cont, basketsize, splitlevel, compress);
871}
872
873////////////////////////////////////////////////////////////////////////////////
874/// Constructor when the branch object is an STL collection.
875///
876/// If splitlevel > 0 this branch in turn is split into sub branches.
877
879: TBranch()
880, fClassName(cont->GetCollectionClass()->GetName())
881, fParentName()
882, fInit(true)
883, fInInitInfo(false)
884, fInitOffsets(false)
885, fTargetClass( fClassName )
886, fCurrentClass()
887, fParentClass()
888, fBranchClass(cont->GetCollectionClass())
889, fBranchID(-1)
890, fReadActionSequence(nullptr)
891, fFillActionSequence(nullptr)
892, fIterators(nullptr)
893, fWriteIterators(nullptr)
894, fPtrIterators(nullptr)
895{
896 Init(parent ? parent->GetTree() : nullptr, parent, bname, cont, basketsize, splitlevel, compress);
897}
898
899////////////////////////////////////////////////////////////////////////////////
900/// Init when the branch object is an STL collection.
901///
902/// If splitlevel > 0 this branch in turn is split into sub branches.
903
905{
906 fCollProxy = cont->Generate();
907 TString name( bname );
908 if (name[name.Length()-1]=='.') {
909 name.Remove(name.Length()-1);
910 }
911 fInitOffsets = false;
913 fInfo = nullptr;
914 fID = -1;
915 fInit = true;
916 fStreamerType = -1; // TVirtualStreamerInfo::kSTLp;
917 fType = 0;
918 fClassVersion = cont->GetCollectionClass()->GetClassVersion();
919 fCheckSum = cont->GetCollectionClass()->GetCheckSum();
920 fBranchCount = nullptr;
921 fBranchCount2 = nullptr;
922 fObject = nullptr;
923 fOnfileObject = nullptr;
924 fMaximum = 0;
925 fBranchOffset = nullptr;
926
927 //Must be set here so that write actions will be properly matched to the ReadLeavesPtr
928 fSTLtype = cont->GetCollectionType();
929 if (fSTLtype < 0) {
931 }
932
933 fTree = tree;
934 fMother = parent ? parent->GetMother() : this;
935 fParent = parent;
937 fFileName = "";
938
939 SetName(name);
940 SetTitle(name);
941 //fClassName = fBranchClass.GetClass()->GetName();
943 if ((compress == -1) && fTree->GetDirectory()) {
945 if (bfile) {
946 fCompress = bfile->GetCompressionSettings();
947 }
948 }
949
950 if (basketsize < 100) {
951 basketsize = 100;
952 }
954
958
959 for (Int_t i = 0; i < fMaxBaskets; ++i) {
960 fBasketBytes[i] = 0;
961 fBasketEntry[i] = 0;
962 fBasketSeek[i] = 0;
963 }
964
965 // Reset the bit kAutoDelete to specify that, when reading,
966 // the object should not be deleted before calling the streamer.
967 SetAutoDelete(false);
968
969 // create sub branches if requested by splitlevel
971 (cont->HasPointers() && splitlevel > TTree::kSplitCollectionOfPointers && cont->GetValueClass() && cont->GetValueClass()->CanSplit() ) )
972 {
973 fType = 4;
974 // ===> Create a leafcount
976 fNleaves = 1;
978 fTree->GetListOfLeaves()->Add(leaf);
979 // ===> create sub branches for each data member of an STL container value class
980 TClass* valueClass = cont->GetValueClass();
981 if (!valueClass) {
982 return;
983 }
984 fClonesName = valueClass->GetName();
987 branchname += "_";
989 leaf->SetName(branchname);
990 leaf->SetTitle(branchname);
995 return;
996 }
997
999 leaf->SetTitle(GetTitle());
1000 fNleaves = 1;
1001 fLeaves.Add(leaf);
1002 fTree->GetListOfLeaves()->Add(leaf);
1005}
1006
1007////////////////////////////////////////////////////////////////////////////////
1008/// Destructor.
1009
1011{
1012 // Release any allocated I/O buffers.
1014 delete fOnfileObject;
1015 fOnfileObject = nullptr;
1016 }
1017 ResetAddress();
1018
1019 delete[] fBranchOffset;
1020 fBranchOffset = nullptr;
1021
1022 fInfo = nullptr;
1023 fBranchCount2 = nullptr;
1024 fBranchCount = nullptr;
1025
1026 if (fType == 4 || fType == 0) {
1027 // Only the top level TBranchElement containing an STL container,
1028 // owns the collectionproxy.
1029 delete fCollProxy;
1030 }
1031 fCollProxy = nullptr;
1032
1033 delete fReadActionSequence;
1034 delete fFillActionSequence;
1035 delete fIterators;
1036 delete fWriteIterators;
1037 delete fPtrIterators;
1038}
1039
1040//
1041// This function is located here to allow inlining by the optimizer.
1042//
1043////////////////////////////////////////////////////////////////////////////////
1044/// Get streamer info for the branch class.
1045
1047{
1048 // Note: we need to find a way to reduce the complexity of
1049 // this often executed condition.
1050 if (!fInfo || (fInfo && (!fInit || !fInfo->IsCompiled()))) {
1051 const_cast<TBranchElement*>(this)->InitInfo();
1052 }
1053 return fInfo;
1054}
1055
1056////////////////////////////////////////////////////////////////////////////////
1057/// Get streamer info for the branch class.
1058
1060{
1061 return GetInfoImp();
1062}
1063
1064////////////////////////////////////////////////////////////////////////////////
1065/// Browse the branch content.
1066
1068{
1070 if (nbranches > 0) {
1072 TBranch* branch=nullptr;
1073 TIter iB(&fBranches);
1074 while((branch=static_cast<TBranch*>(iB()))) {
1075 if (branch->IsFolder()) persistentBranches.Add(branch);
1076 else {
1077 // only show branches corresponding to persistent members
1078 TClass* cl=nullptr;
1079 if (strlen(GetClonesName()))
1080 // this works both for top level branches and for sub-branches,
1081 // as GetClonesName() is properly updated for sub-branches
1082 cl=fClonesClass;
1083 else {
1085
1086 // check if we're in a sub-branch of this class
1087 // we can only find out asking the streamer given our ID
1088 TStreamerElement *element=nullptr;
1089 TClass* clsub=nullptr;
1090 auto info = (fID >= 0) ? GetInfoImp() : nullptr;
1091 if (info
1092 && info->IsCompiled()
1093 && ((element=info->GetElement(fID)))
1094 && ((clsub=element->GetClassPointer())))
1095 cl=clsub;
1096 }
1097 if (cl) {
1098 TString strMember=branch->GetName();
1099 Size_t mempos=strMember.Last('.');
1100 if (mempos!=kNPOS)
1101 strMember.Remove(0, (Int_t)mempos+1);
1102 mempos=strMember.First('[');
1103 if (mempos!=kNPOS)
1104 strMember.Remove((Int_t)mempos);
1106 if (!m || m->IsPersistent()) persistentBranches.Add(branch);
1107 } else persistentBranches.Add(branch);
1108 } // branch if not a folder
1109 }
1110 persistentBranches.Browse(b);
1111 // add all public const methods without params
1112 if (GetBrowsables() && GetBrowsables()->GetSize())
1113 GetBrowsables()->Browse(b);
1114 } else {
1115 if (GetBrowsables() && GetBrowsables()->GetSize()) {
1116 GetBrowsables()->Browse(b);
1117 return;
1118 }
1119 // Get the name and strip any extra brackets
1120 // in order to get the full arrays.
1121 TString slash("/");
1122 TString escapedSlash("\\/");
1123 TString name = GetName();
1124 Int_t pos = name.First('[');
1125 if (pos != kNPOS) {
1126 name.Remove(pos);
1127 }
1129 if (GetMother()) {
1131 pos = mothername.First('[');
1132 if (pos != kNPOS) {
1133 mothername.Remove(pos);
1134 }
1135 Int_t len = mothername.Length();
1136 if (len) {
1137 if (mothername(len-1) != '.') {
1138 // We do not know for sure whether the mother's name is
1139 // already preprended. So we need to check:
1140 // a) it is prepended
1141 // b) it is NOT the name of a daughter (i.e. mothername.mothername exist)
1143 doublename.Append(".");
1144 Int_t isthere = (name.Index(doublename) == 0);
1145 if (!isthere) {
1146 name.Prepend(doublename);
1147 } else {
1149 doublename.Append(mothername);
1150 isthere = (name.Index(doublename) == 0);
1151 if (!isthere) {
1152 mothername.Append(".");
1153 name.Prepend(mothername);
1154 }
1155 } else {
1156 // Nothing to do because the mother's name is
1157 // already in the name.
1158 }
1159 }
1160 } else {
1161 // If the mother's name end with a dot then
1162 // the daughter probably already contains the mother's name
1163 if (name.Index(mothername) == kNPOS) {
1164 name.Prepend(mothername);
1165 }
1166 }
1167 }
1168 }
1169 name.ReplaceAll(slash, escapedSlash);
1170 GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
1171 if (gPad) {
1172 gPad->Update();
1173 }
1174 }
1175}
1176
1177////////////////////////////////////////////////////////////////////////////////
1178/// Set branch and leaf name and title in the case of a container sub-branch.
1179
1181{
1183
1185
1187 if (indexname[indexname.Length()-1]=='.') {
1188 indexname.Remove(indexname.Length()-1);
1189 }
1190 indexname += "_";
1191
1192 for (Int_t i = 0; i < nbranches; ++i) {
1193 TBranchElement* bre = static_cast<TBranchElement*>(fBranches.At(i));
1194 if (!bre)
1195 continue;
1196 if (fType == 3) {
1197 bre->SetType(31);
1198 } else if (fType == 4) {
1199 bre->SetType(41);
1200 } else {
1201 Error("BuildTitle", "This cannot happen, fType of parent is not 3 or 4!");
1202 }
1203 bre->fCollProxy = GetCollectionProxy();
1204 bre->BuildTitle(name);
1205 const char* fin = strrchr(bre->GetTitle(), '.');
1206 if (fin == nullptr) {
1207 continue;
1208 }
1209 // The branch counter for a sub-branch of a container is the container master branch.
1210 bre->SetBranchCount(this);
1211 TLeafElement* lf = static_cast<TLeafElement*>(bre->GetListOfLeaves()->At(0));
1212 // If branch name is of the form fTracks.fCovar[3][4], then
1213 // set the title to fCovar[fTracks_].
1214 branchname = fin+1;
1215 Ssiz_t dim = branchname.First('[');
1216 if (dim>=0) {
1217 branchname.Remove(dim);
1218 }
1219 branchname += TString::Format("[%s]", indexname.Data());
1220 bre->SetTitle(branchname);
1221 if (lf) {
1222 lf->SetTitle(branchname);
1223 }
1224 // Is there a secondary branchcount?
1225 //
1226 // fBranchCount2 points to the secondary branchcount
1227 // in case a TClonesArray element itself has a branchcount.
1228 //
1229 // Example: In Event class with TClonesArray fTracks of Track objects.
1230 // if the Track object has two members
1231 // Int_t fNpoint;
1232 // Float_t *fPoints; //[fNpoint]
1233 // In this case the TBranchElement fTracks.fPoints has
1234 // -its primary branchcount pointing to the branch fTracks
1235 // -its secondary branchcount pointing to fTracks.fNpoint
1236 Int_t stype = bre->GetStreamerType();
1237 // FIXME: Should 60 be included here?
1238 if ((stype > 40) && (stype < 61)) {
1239 TString name2 (bre->GetName());
1240 Ssiz_t bn = name2.Last('.');
1241 if (bn<0) {
1242 continue;
1243 }
1244 TStreamerBasicPointer *el = dynamic_cast<TStreamerBasicPointer*>(bre->GetInfoImp()->GetElements()->FindObject(name2.Data()+bn+1));
1245 name2.Remove(bn+1);
1246 if (el) name2 += el->GetCountName();
1248 bre->SetBranchCount2(bc2);
1249 }
1250 bre->SetReadLeavesPtr();
1251 bre->SetFillLeavesPtr();
1252 }
1253}
1254
1255////////////////////////////////////////////////////////////////////////////////
1256/// Loop on all leaves of this branch to fill the basket buffer.
1257///
1258/// The function returns the number of bytes committed to the
1259/// individual branches. If a write error occurs, the number of
1260/// bytes returned is -1. If no data are written, because, e.g.,
1261/// the branch is disabled, the number of bytes returned is 0.
1262///
1263/// Note: We not not use any member functions from TLeafElement!
1264
1266{
1267 Int_t nbytes = 0;
1268 Int_t nwrite = 0;
1269 Int_t nerror = 0;
1271
1273
1274 //
1275 // If we are a top-level branch, update addresses.
1276 //
1277
1278 if (fID < 0) {
1279 if (!fObject) {
1280 Error("Fill", "attempt to fill branch %s while address is not set", GetName());
1281 return 0;
1282 }
1283 }
1284
1285 //
1286 // If the tree has a TRefTable, set the current branch if
1287 // branch is not a basic type.
1288 //
1289
1290 // FIXME: This test probably needs to be extended past 10.
1291 if ((fType >= -1) && (fType < 10)) {
1293 if (bref) {
1294 fBranchID = bref->SetParent(this, fBranchID);
1295 }
1296 }
1297
1298 if (!nbranches) {
1299 // No sub-branches.
1300 if (!TestBit(kDoNotProcess)) {
1302 if (nwrite < 0) {
1303 Error("Fill", "Failed filling branch:%s, nbytes=%d", GetName(), nwrite);
1304 ++nerror;
1305 } else {
1306 nbytes += nwrite;
1307 }
1308 }
1309 } else {
1310 // We have sub-branches.
1311 if (fType == 3 || fType == 4) {
1312 // TClonesArray or STL container counter
1314 if (nwrite < 0) {
1315 Error("Fill", "Failed filling branch:%s, nbytes=%d", GetName(), nwrite);
1316 ++nerror;
1317 } else {
1318 nbytes += nwrite;
1319 }
1320 } else {
1321 ++fEntries;
1322 }
1323 for (Int_t i = 0; i < nbranches; ++i) {
1324 TBranchElement* branch = static_cast<TBranchElement*>(fBranches[i]);
1325 if (!branch->TestBit(kDoNotProcess)) {
1326 nwrite = branch->FillImpl(imtHelper);
1327 if (nwrite < 0) {
1328 Error("Fill", "Failed filling branch:%s.%s, nbytes=%d", GetName(), branch->GetName(), nwrite);
1329 nerror++;
1330 } else {
1331 nbytes += nwrite;
1332 }
1333 }
1334 }
1335 }
1336
1337 if (fTree->Debug() > 0) {
1338 // Debugging.
1340 if ((entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
1341 printf("Fill: %lld, branch=%s, nbytes=%d\n", entry, GetName(), nbytes);
1342 }
1343 }
1344
1345 if (nerror != 0) {
1346 return -1;
1347 }
1348
1349 return nbytes;
1350}
1351
1352////////////////////////////////////////////////////////////////////////////////
1353/// Write leaves into i/o buffers for this branch.
1354/// For the case where the branch is set in MakeClass mode (decomposed object).
1355
1357{
1359
1360 //
1361 // Silently do nothing if we have no user i/o buffer.
1362 //
1363
1364 if (!fObject) {
1365 return;
1366 }
1367
1368 // -- TClonesArray top-level branch. Write out number of entries, sub-branch writes the entries themselves.
1369 if(fType == 3) {
1370 // fClonesClass can not be zero since we are of type 3, see TBranchElement::Init
1372 if (!si) {
1373 Error("FillLeaves", "Cannot get streamer info for branch '%s' class '%s'", GetName(), fClonesClass->GetName());
1374 return;
1375 }
1376 b.ForceWriteInfo(si,false);
1377 Int_t* nptr = reinterpret_cast<Int_t*>(fAddress);
1378 b << *nptr;
1379 } else if (fType == 31) {
1380 // -- TClonesArray sub-branch. Write out the entries in the TClonesArray.
1381 // -- A MakeClass() tree, we must use fAddress instead of fObject.
1382 if (!fAddress) {
1383 // FIXME: Enable this message.
1384 //Error("FillLeaves", "Branch address not set for branch '%s'!", GetName());
1385 return;
1386 }
1388 if (atype > 54) {
1389 // Note: We are not supporting kObjectp, kAny, kObjectp,
1390 // kObjectP, kTString, kTObject, kTNamed, kAnyp,
1391 // kAnyP, kSTLp, kSTL, kSTLstring, kStreamer,
1392 // kStreamLoop here, nor pointers to varying length
1393 // arrays of them either.
1394 // Nor do we support pointers to varying length
1395 // arrays of kBits, kLong64, kULong64, nor kBool.
1396 return;
1397 }
1398 Int_t* nn = reinterpret_cast<Int_t*>(fBranchCount->GetAddress());
1399 if (!nn) {
1400 Error("FillLeaves", "The branch counter address was zero!");
1401 return;
1402 }
1403 Int_t n = *nn;
1404 if (atype > 40) {
1405 // Note: We are not supporting pointer to varying length array.
1406 Error("FillLeaves", "Clonesa: %s, n=%d, sorry not supported yet", GetName(), n);
1407 return;
1408 }
1409 if (atype > 20) {
1410 atype -= 20;
1411 TLeafElement* leaf = static_cast<TLeafElement*>(fLeaves.UncheckedAt(0));
1412 n = n * leaf->GetLenStatic();
1413 }
1414 switch (atype) {
1415 // Note: Type 0 is a base class and cannot happen here, see Unroll().
1416 case TVirtualStreamerInfo::kChar /* 1 */: { b.WriteFastArray(reinterpret_cast<Char_t*>(fAddress), n); break; }
1417 case TVirtualStreamerInfo::kShort /* 2 */: { b.WriteFastArray(reinterpret_cast<Short_t*>(fAddress), n); break; }
1418 case TVirtualStreamerInfo::kInt /* 3 */: { b.WriteFastArray(reinterpret_cast<Int_t*>(fAddress), n); break; }
1419 case TVirtualStreamerInfo::kLong /* 4 */: { b.WriteFastArray(reinterpret_cast<Long_t*>(fAddress), n); break; }
1420 case TVirtualStreamerInfo::kFloat /* 5 */: { b.WriteFastArray(reinterpret_cast<Float_t*>(fAddress), n); break; }
1421 case TVirtualStreamerInfo::kCounter /* 6 */: { b.WriteFastArray(reinterpret_cast<Int_t*>(fAddress), n); break; }
1422 // FIXME: We do nothing with type 7 (TVirtualStreamerInfo::kCharStar, char*) here!
1423 case TVirtualStreamerInfo::kDouble /* 8 */: { b.WriteFastArray(reinterpret_cast<Double_t*>(fAddress), n); break; }
1424 case TVirtualStreamerInfo::kDouble32 /* 9 */: {
1426 // coverity[returned_null] structurally si->fComp (used in GetElem) can not be null.
1427 TStreamerElement* se = si->GetElement(fID);
1428 Double_t* xx = reinterpret_cast<Double_t*>(fAddress);
1429 for (Int_t ii = 0; ii < n; ++ii) {
1430 b.WriteDouble32(&(xx[ii]),se);
1431 }
1432 break;
1433 }
1434 case TVirtualStreamerInfo::kFloat16 /* 19 */: {
1436 // coverity[dereference] structurally si can not be null.
1437 TStreamerElement* se = static_cast<TStreamerElement*>(si->GetElement(fID));
1438 Float_t* xx = reinterpret_cast<Float_t*>(fAddress);
1439 for (Int_t ii = 0; ii < n; ++ii) {
1440 b.WriteFloat16(&(xx[ii]),se);
1441 }
1442 break;
1443 }
1444 // Note: Type 10 is unused for now.
1445 case TVirtualStreamerInfo::kUChar /* 11 */: { b.WriteFastArray(reinterpret_cast<UChar_t*>(fAddress), n); break; }
1446 case TVirtualStreamerInfo::kUShort /* 12 */: { b.WriteFastArray(reinterpret_cast<UShort_t*>(fAddress), n); break; }
1447 case TVirtualStreamerInfo::kUInt /* 13 */: { b.WriteFastArray(reinterpret_cast<UInt_t*>(fAddress), n); break; }
1448 case TVirtualStreamerInfo::kULong /* 14 */: { b.WriteFastArray(reinterpret_cast<ULong_t*>(fAddress), n); break; }
1449 // FIXME: This is wrong!!! TVirtualStreamerInfo::kBits is a variable length type.
1450 case TVirtualStreamerInfo::kBits /* 15 */: { b.WriteFastArray(reinterpret_cast<UInt_t*>(fAddress), n); break; }
1451 case TVirtualStreamerInfo::kLong64 /* 16 */: { b.WriteFastArray(reinterpret_cast<Long64_t*>(fAddress), n); break; }
1452 case TVirtualStreamerInfo::kULong64 /* 17 */: { b.WriteFastArray(reinterpret_cast<ULong64_t*>(fAddress), n); break; }
1453 case TVirtualStreamerInfo::kBool /* 18 */: { b.WriteFastArray(reinterpret_cast<bool*>(fAddress), n); break; }
1454 }
1455 }
1456}
1457
1458////////////////////////////////////////////////////////////////////////////////
1459/// Write leaves into i/o buffers for this branch.
1460/// Case of a collection (fType == 4).
1461
1463{
1464 // -- STL container top-level branch. Write out number of entries, sub-branch writes the entries themselves.
1466
1467 //
1468 // Silently do nothing if we have no user i/o buffer.
1469 //
1470
1471 if (!fObject) {
1472 return;
1473 }
1474
1476 Int_t n = 0;
1477 // We are in a block so the helper pops as soon as possible.
1479 n = proxy->Size();
1480
1481 if (n > fMaximum) {
1482 fMaximum = n;
1483 }
1484 b << n;
1485
1488 } else {
1489 //NOTE: this does not work for not vectors since the CreateIterators expects a TGenCollectionProxy::TStaging as its argument!
1490 //NOTE: and those not work in general yet, since the TStaging object is neither created nor passed.
1491 // We need to review how to avoid the need for a TStaging during the writing.
1494 } else {
1496 }
1497 }
1498
1499}
1500
1501////////////////////////////////////////////////////////////////////////////////
1502/// Write leaves into i/o buffers for this branch.
1503/// Case of a data member within a collection (fType == 41).
1504
1506{
1508
1509 //
1510 // Silently do nothing if we have no user i/o buffer.
1511 //
1512
1513 if (!fObject) {
1514 return;
1515 }
1516
1517 // FIXME: This wont work if a pointer to vector is split!
1519 // Note: We cannot pop the proxy here because we need it for the i/o.
1520 TStreamerInfo* si = static_cast<TStreamerInfo*>(GetInfoImp());
1521 if (!si) {
1522 Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1523 return;
1524 }
1525
1527 R__ASSERT(nullptr!=iter);
1528 b.ApplySequenceVecPtr(*fFillActionSequence,iter->fBegin,iter->fEnd);
1529}
1530
1531////////////////////////////////////////////////////////////////////////////////
1532/// Write leaves into i/o buffers for this branch.
1533/// Case of a data member within a collection (fType == 41).
1534
1536{
1538
1539 //
1540 // Silently do nothing if we have no user i/o buffer.
1541 //
1542
1543 if (!fObject) {
1544 return;
1545 }
1546
1547 // FIXME: This wont work if a pointer to vector is split!
1549
1550 // Note: We cannot pop the proxy here because we need it for the i/o.
1551 TStreamerInfo* si = static_cast<TStreamerInfo*>(GetInfoImp());
1552 if (!si) {
1553 Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1554 return;
1555 }
1556
1558 b.ApplySequence(*fFillActionSequence,iter->fBegin,iter->fEnd);
1559
1560}
1561
1562////////////////////////////////////////////////////////////////////////////////
1563/// Write leaves into i/o buffers for this branch.
1564/// Case of a data member within a collection (fType == 41).
1565
1567{
1569
1570 //
1571 // Silently do nothing if we have no user i/o buffer.
1572 //
1573
1574 if (!fObject) {
1575 return;
1576 }
1577
1578 // FIXME: This wont work if a pointer to vector is split!
1580 // Note: We cannot pop the proxy here because we need it for the i/o.
1581 TStreamerInfo* si = static_cast<TStreamerInfo*>(GetInfoImp());
1582 if (!si) {
1583 Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1584 return;
1585 }
1586
1588 R__ASSERT(nullptr!=iter);
1589 b.ApplySequence(*fFillActionSequence,iter->fBegin,iter->fEnd);
1590
1591}
1592
1593////////////////////////////////////////////////////////////////////////////////
1594/// Write leaves into i/o buffers for this branch.
1595/// Case of a data member within a collection (fType == 41).
1596
1598{
1600
1601 //
1602 // Silently do nothing if we have no user i/o buffer.
1603 //
1604
1605 if (!fObject) {
1606 return;
1607 }
1608
1609 // FIXME: This wont work if a pointer to vector is split!
1611 // Note: We cannot pop the proxy here because we need it for the i/o.
1612 TStreamerInfo* si = static_cast<TStreamerInfo*>(GetInfoImp());
1613 if (!si) {
1614 Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1615 return;
1616 }
1617
1619 R__ASSERT(nullptr!=iter);
1620 b.ApplySequence(*fFillActionSequence,iter->fBegin,iter->fEnd);
1621
1622}
1623
1624////////////////////////////////////////////////////////////////////////////////
1625/// Write leaves into i/o buffers for this branch.
1626/// Case of a TClonesArray (fType == 3).
1627
1629{
1630 // -- TClonesArray top-level branch. Write out number of entries, sub-branch writes the entries themselves.
1632
1633 //
1634 // Silently do nothing if we have no user i/o buffer.
1635 //
1636
1637 if (!fObject) {
1638 return;
1639 }
1640
1641 TClonesArray* clones = reinterpret_cast<TClonesArray*>(fObject);
1642 Int_t n = clones->GetEntriesFast();
1643 if (n > fMaximum) {
1644 fMaximum = n;
1645 }
1646 b << n;
1647}
1648
1649////////////////////////////////////////////////////////////////////////////////
1650/// Write leaves into i/o buffers for this branch.
1651/// Case of a data member within a TClonesArray (fType == 31).
1652
1654{
1656
1657 //
1658 // Silently do nothing if we have no user i/o buffer.
1659 //
1660
1661 if (!fObject) {
1662 return;
1663 }
1664
1665 TClonesArray* clones = reinterpret_cast<TClonesArray*>(fObject);
1666 Int_t n = clones->GetEntriesFast();
1667 TStreamerInfo* si = static_cast<TStreamerInfo*>(GetInfoImp());
1668 if (!si) {
1669 Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1670 return;
1671 }
1672
1673 char **arr = reinterpret_cast<char **>(clones->GetObjectRef(nullptr));
1674 char **end = arr + n;
1675 b.ApplySequenceVecPtr(*fFillActionSequence,arr,end);
1676}
1677
1678////////////////////////////////////////////////////////////////////////////////
1679/// Write leaves into i/o buffers for this branch.
1680/// Case of a non TObject, non collection class with a custom streamer
1681
1683{
1685
1686 //
1687 // Silently do nothing if we have no user i/o buffer.
1688 //
1689
1690 if (!fObject) {
1691 return;
1692 }
1693
1694 //
1695 // Remember tobjects written to the buffer so that
1696 // pointers are handled correctly later.
1697
1698 if (TestBit(kBranchObject)) {
1699 b.MapObject(reinterpret_cast<TObject*>(fObject));
1700 } else if (TestBit(kBranchAny)) {
1701 b.MapObject(fObject, fBranchClass);
1702 }
1703
1705}
1706
1707////////////////////////////////////////////////////////////////////////////////
1708/// Write leaves into i/o buffers for this branch.
1709/// For split-class branch, base class branch, data member branch, or top-level branch.
1710/// which do have a branch count and are not a counter.
1711
1713{
1715 /*
1716 ValidateAddress();
1717
1718 //
1719 // Silently do nothing if we have no user i/o buffer.
1720 //
1721
1722 if (!fObject) {
1723 return;
1724 }
1725 */
1726}
1727
1728////////////////////////////////////////////////////////////////////////////////
1729/// Write leaves into i/o buffers for this branch.
1730/// For split-class branch, base class branch, data member branch, or top-level branch.
1731/// which do not have a branch count and are a counter.
1732
1734{
1736
1737 //
1738 // Silently do nothing if we have no user i/o buffer.
1739 //
1740
1741 if (!fObject) {
1742 return;
1743 }
1744 // -- Top-level, data member, base class, or split class branch.
1745 // A non-split top-level branch (0, and fID == -1)), a non-split object (0, and fID > -1), or a base class (1), or a split (non-TClonesArray, non-STL container) object (2). Write out the object.
1746 // Note: A split top-level branch (0, and fID == -2) should not happen here, see Fill().
1747 // FIXME: What happens with a split base class branch,
1748 // or a split class branch???
1750 if (!si) {
1751 Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1752 return;
1753 }
1754 // Since info is not null, fFillActionSequence is not null either.
1755 b.ApplySequence(*fFillActionSequence, fObject);
1756 // Int_t n = si->WriteBufferAux(b, &fObject, fID, 1, 0, 0);
1757
1758 Int_t n = *reinterpret_cast<Int_t*>(fObject + si->TStreamerInfo::GetElementOffset(fID)); // or GetInfoImp()->GetTypedValue<Int_t>(&fObject, fID, j, -1);
1759 if (n > fMaximum) {
1760 fMaximum = n;
1761 }
1762
1763}
1764
1765////////////////////////////////////////////////////////////////////////////////
1766/// Write leaves into i/o buffers for this branch.
1767/// For split-class branch, base class branch, data member branch, or top-level branch.
1768/// which do not have a branch count and are not a counter.
1769
1771{
1773
1774 //
1775 // Silently do nothing if we have no user i/o buffer.
1776 //
1777
1778 if (!fObject) {
1779 return;
1780 }
1781
1782 if (TestBit(kBranchObject)) {
1783 b.MapObject(reinterpret_cast<TObject*>(fObject));
1784 } else if (TestBit(kBranchAny)) {
1785 b.MapObject(fObject, fBranchClass);
1786 }
1787
1788 // -- Top-level, data member, base class, or split class branch.
1789 // A non-split top-level branch (0, and fID == -1)), a non-split object (0, and fID > -1), or a base class (1), or a split (non-TClonesArray, non-STL container) object (2). Write out the object.
1790 // Note: A split top-level branch (0, and fID == -2) should not happen here, see Fill().
1791 // FIXME: What happens with a split base class branch,
1792 // or a split class branch???
1794 if (!si) {
1795 Error("FillLeaves", "Cannot get streamer info for branch '%s'", GetName());
1796 return;
1797 }
1798 // Since info is not null, fFillActionSequence is not null either.
1799 b.ApplySequence(*fFillActionSequence, fObject);
1800
1801}
1802
1803////////////////////////////////////////////////////////////////////////////////
1804/// Remove trailing dimensions and make sure
1805/// there is a trailing dot.
1806
1807static void R__CleanName(std::string &name)
1808{
1809 if (name[name.length()-1]==']') {
1810 std::size_t dim = name.find_first_of('[');
1811 if (dim != std::string::npos) {
1812 name.erase(dim);
1813 }
1814 }
1815 if (name[name.size()-1] != '.') {
1816 name += '.';
1817 }
1818}
1819
1820////////////////////////////////////////////////////////////////////////////////
1821/// Find the immediate sub-branch with passed name.
1822
1824{
1825 // The default behavior of TBranch::FindBranch is sometimes
1826 // incorrect if this branch represent a base class, since
1827 // the base class name might or might not be in the name
1828 // of the sub-branches and might or might not be in the
1829 // name being passed.
1830
1831 if (fID >= 0) {
1833 TStreamerElement* se = si->GetElement(fID);
1834 if (se && se->IsBase()) {
1835 // We allow the user to pass only the last dotted component of the name.
1836 UInt_t len = strlen(name);
1837 std::string longnm;
1838 longnm.reserve(fName.Length()+len+3); // Enough space of fName + name + dots
1839 longnm = fName.Data();
1841 longnm += name;
1842 std::string longnm_parent;
1843 longnm_parent.reserve(fName.Length()+len+3);
1846 longnm_parent += name; // Name without the base class name
1847
1848 UInt_t namelen = strlen(name);
1849
1850 TBranch* branch = nullptr;
1852 for(Int_t i = 0; i < nbranches; ++i) {
1853 branch = static_cast<TBranch*>(fBranches.UncheckedAt(i));
1854
1855 const char *brname = branch->GetName();
1857 if (brname[brlen-1]==']') {
1858 const char *dim = strchr(brname,'[');
1859 if (dim) {
1860 brlen = dim - brname;
1861 }
1862 }
1863 if (namelen == brlen /* same effective size */
1864 && strncmp(name,brname,brlen) == 0) {
1865 return branch;
1866 }
1867 if (brlen == longnm.length()
1868 && strncmp(longnm.c_str(),brname,brlen) == 0) {
1869 return branch;
1870 }
1871 // This check is specific to base class
1872 if (brlen == longnm_parent.length()
1873 && strncmp(longnm_parent.c_str(),brname,brlen) == 0) {
1874 return branch;
1875 }
1876
1877 if (namelen>brlen && name[brlen]=='.' && strncmp(name,brname,brlen)==0) {
1878 // The prefix subbranch name match the branch name.
1879 return branch->FindBranch(name+brlen+1);
1880 }
1881 }
1882 }
1883 }
1885 if (!result) {
1886 // Look in base classes if any
1888 for(Int_t i = 0; i < nbranches; ++i) {
1889 TObject *obj = fBranches.UncheckedAt(i);
1890 if(obj->IsA() != TBranchElement :: Class() )
1891 continue;
1892 TBranchElement *br = static_cast<TBranchElement*>(obj);
1893 TVirtualStreamerInfo* si = br->GetInfoImp();
1894 if (si && br->GetID() >= 0) {
1895 TStreamerElement* se = si->GetElement(br->GetID());
1896 if (se && se->IsBase()) {
1897 result = br->FindBranch(name);
1898 }
1899 }
1900 }
1901 }
1902 return result;
1903}
1904
1905////////////////////////////////////////////////////////////////////////////////
1906/// Find the leaf corresponding to the name 'searchname'.
1907
1909{
1911
1912 if (leaf==nullptr && GetListOfLeaves()->GetEntries()==1) {
1913 TBranch *br = GetMother()->GetSubBranch( this );
1914 if( br->IsA() != TBranchElement::Class() )
1915 return nullptr;
1916
1917 TBranchElement *parent = static_cast<TBranchElement*>(br);
1918 if (parent==this || parent->GetID()<0 ) return nullptr;
1919
1920 TVirtualStreamerInfo* si = parent->GetInfoImp();
1921 TStreamerElement* se = si->GetElement(parent->GetID());
1922
1923 if (! se->IsBase() ) return nullptr;
1924
1925 br = GetMother()->GetSubBranch( parent );
1926 if( br->IsA() != TBranchElement::Class() )
1927 return nullptr;
1928
1929 TBranchElement *grand_parent = static_cast<TBranchElement*>(br);
1930
1931 std::string longname( grand_parent->GetName() );
1933 longname += name;
1934
1935 std::string leafname( GetListOfLeaves()->At(0)->GetName() );
1936
1937 if ( longname == leafname ) {
1938 return static_cast<TLeaf*>(GetListOfLeaves()->At(0));
1939 }
1940 }
1941 return leaf;
1942}
1943
1944////////////////////////////////////////////////////////////////////////////////
1945/// Get the branch address.
1946///
1947/// If we are *not* owned by a MakeClass() tree:
1948///
1949/// - If we are a top-level branch, return a pointer
1950/// - to the pointer to our object.
1951///
1952/// If we are *not* a top-level branch, return a pointer
1953/// to our object.
1954///
1955/// If we are owned by a MakeClass() tree:
1956///
1957/// - Return a pointer to our object.
1958
1960{
1962 return fAddress;
1963}
1964
1965
1966// For a mother branch of type 3 or 4, find the 'correct' StreamerInfo for the
1967// content of the collection by find a sub-branch corresponding to a direct data member
1968// of the containee class (valueClass)
1969// Default to the current StreamerInfo if none are found.
1971{
1973
1974 // Search for the correct version.
1976 if (!subbe->fInfo)
1977 subbe->SetupInfo();
1978 if (valueClass == subbe->fInfo->GetClass()) { // Use GetInfo to provoke its creation.
1979 localInfo = subbe->fInfo;
1980 break;
1981 }
1982 }
1983 if (!localInfo) {
1984 // This is likely sub-optimal as we really should call GetFile but it is non-const.
1985 auto file = fDirectory ? fDirectory->GetFile() : nullptr;
1986 if (file && file->GetSeekInfo()) {
1987 localInfo = static_cast<TStreamerInfo*>(file->GetStreamerInfoCache()->FindObject(valueClass->GetName()));
1988 if (localInfo) {
1989 if (valueClass->IsVersioned()) {
1990 localInfo = valueClass->GetStreamerInfo(localInfo->GetClassVersion());
1991 } else {
1992 localInfo = valueClass->FindStreamerInfo(localInfo->GetCheckSum());
1993 if (localInfo) {
1994 // Now that we found it, we need to make sure it is initialize (Find does not initialize the StreamerInfo).
1995 localInfo = valueClass->GetStreamerInfo(localInfo->GetClassVersion());
1996 }
1997 }
1998 }
1999 }
2000 }
2001 if (!localInfo)
2002 localInfo = valueClass->GetStreamerInfo();
2003
2004 if (localInfo) {
2005 // See if we need any conversion.
2008 : nullptr;
2009 // For TClonesArray, the rest of the code probably does not support change in
2010 // value class, but if it does, we would have to look up the target value class
2011 // in the TClonesArray instance.
2012 // if (type == 3 && instance) targetValueClass = (reinterpret_cast<TClonesArray*>(instance))->GetClass();
2013
2014 if (targetValueClass && localInfo->GetClass() != targetValueClass) {
2015 localInfo = targetValueClass->GetConversionStreamerInfo(localInfo->GetClass(),
2016 localInfo->GetClassVersion());
2017 }
2018 }
2019 return static_cast<TStreamerInfo*>(localInfo);
2020}
2021
2022namespace {
2024 size_t ndata = info->GetNelement();
2025 for (size_t i =0; i < ndata; ++i) {
2026 TStreamerElement *nextel = info->GetElement(i);
2027
2028 if (nextel->GetType() == TStreamerInfo::kCacheDelete
2029 || nextel->GetType() == TStreamerInfo::kCacheNew) {
2030 continue;
2031 }
2032
2033 TString ename = prefix + nextel->GetName();
2034
2035 if (ename[0]=='*')
2036 ename.Remove(0,1);
2037
2038 Ssiz_t pos;
2039 while ((pos = ename.Last('[')) != TString::kNPOS) {
2040 ename = ename.Remove(pos);
2041 }
2042
2043 TBranchElement *be = static_cast<TBranchElement*>(branches.FindObject(ename));
2044 if (nextel->IsA() == TStreamerArtificial::Class()
2045 && be == nullptr) {
2046
2047 ids.push_back(i);
2048 ids.back().fElement = nextel;
2049 ids.back().fInfo = info;
2050 }
2051
2052 if (nextel->CannotSplit() || nextel->IsTransient() || nextel->GetOffset() == TStreamerInfo::kMissing)
2053 continue;
2054
2055 if (!be && nextel->IsBase()) {
2056 // We could be in the case of a branch created from a Folder or
2057 // a top level branch with a non-trailing dot in its name (case inadvertently confused with the folder case).
2058 // In those case, the name of the base class is *not* used to create the corresponding branch.
2059 TString subprefix(prefix);
2060 if (subprefix.Length() && subprefix[subprefix.Length()-1] == '.')
2061 subprefix.Remove(subprefix.Length()-1);
2062
2063 be = static_cast<TBranchElement*>(branches.FindObject(subprefix));
2064 if (be) {
2065 // There is at least 'one' base class branch all with the same name, so let's find the
2066 // right one.
2067 TClass *expectedClass = nullptr;
2069 if (0 != be->GetExpectedType(expectedClass,expectedType)
2070 || expectedClass != nextel->GetClassPointer())
2071 {
2072 be = nullptr;
2073 Int_t nbranches = branches.GetEntriesFast();
2074 for (Int_t bi = 0; bi < nbranches; ++bi) {
2075 TBranchElement* branch = static_cast<TBranchElement*>(branches[bi]);
2076 if (subprefix != branch->GetName())
2077 continue;
2078 if (0 == branch->GetExpectedType(expectedClass,expectedType)
2079 && expectedClass == nextel->GetClassPointer())
2080 {
2081 be = branch;
2082 break;
2083 }
2084 }
2085 } // else we have already found the right branch.
2086 }
2087 }
2088
2089 TClass *elementClass = nextel->GetClassPointer();
2090 if (elementClass && (!be || be->GetType() == -2)) {
2091 // Recurse on sub-objects.
2092 TStreamerInfo *nextinfo = nullptr;
2093
2094 // nextinfo_version = ....
2095 auto search = be ? be->GetListOfBranches() : &branches;
2096 TVirtualArray *onfileObject = nullptr;
2097
2099 if (prefix.Length() && nextel->IsA() == TStreamerBase::Class()) {
2100 // We skip the name of the base class if there is already a prefix.
2101 // See TBranchElement::Unroll
2102 subprefix = prefix;
2103 } else {
2104 subprefix = ename + ".";
2105 }
2106 auto nbranches = search->GetEntriesFast();
2107 bool foundRelatedSplit = false;
2108 for (Int_t bi = 0; bi < nbranches; ++bi) {
2109 TBranchElement* subbe = static_cast<TBranchElement*>(search->At(bi));
2110 bool matchSubPrefix = strncmp(subbe->GetFullName(), subprefix.Data(), subprefix.Length()) == 0;
2111 if (!foundRelatedSplit)
2113 if (elementClass == subbe->GetInfo()->GetClass() // Use GetInfo to provoke its creation.
2114 && subbe->GetOnfileObject()
2115 && matchSubPrefix)
2116 {
2117 nextinfo = subbe->GetInfo();
2118 onfileObject = subbe->GetOnfileObject();
2119 break;
2120 }
2121 }
2122
2123 if (!foundRelatedSplit) {
2124 continue;
2125 }
2126
2127 if (!nextinfo) {
2128 nextinfo = static_cast<TStreamerInfo *>(elementClass->GetStreamerInfo());
2129 if (elementClass->GetCollectionProxy() && elementClass->GetCollectionProxy()->GetValueClass()) {
2130 nextinfo = static_cast<TStreamerInfo *>(elementClass->GetCollectionProxy()->GetValueClass()->GetStreamerInfo()); // NOTE: need to find the right version
2131 }
2132 }
2133 ids.emplace_back(nextinfo, offset + nextel->GetOffset());
2134 if (!onfileObject && nextinfo && nextinfo->GetNelement() && nextinfo->GetElement(0)->GetType() == TStreamerInfo::kCacheNew) {
2135 onfileObject = new TVirtualArray( info->GetElement(0)->GetClassPointer(), 1 /* is that always right? */ );
2136 ids.back().fNestedIDs->fOwnOnfileObject = true;
2137 }
2138 ids.back().fNestedIDs->fOnfileObject = onfileObject;
2139 GatherArtificialElements(branches, ids.back().fNestedIDs->fIDs, subprefix, nextinfo, offset + nextel->GetOffset());
2140 if (ids.back().fNestedIDs->fIDs.empty())
2141 ids.pop_back();
2142 }
2143 }
2144};
2145} // Anonymous namespace.
2146
2147
2148////////////////////////////////////////////////////////////////////////////////
2149/// Set the value of fInfo. This is part one of InitInfo.
2150/// To be used as:
2151/// if (!fInfo)
2152/// SetupInfo();
2153/// It would only be used within InitInfo (and its callees)
2154
2156{
2157 // We did not already have streamer info, so now we must find it.
2159
2160 //------------------------------------------------------------------------
2161 // Check if we're dealing with the name change
2162 //////////////////////////////////////////////////////////////////////////
2163
2164 TClass* targetClass = nullptr;
2165 if( fTargetClass.GetClassName()[0] ) {
2167 if (!targetClass && GetCollectionProxy()) {
2168 // We are in the case where the branch holds a custom collection
2169 // proxy but the dictionary is not loaded, calling
2170 // GetCollectionProxy had the side effect of creating the TClass
2171 // corresponding to this emulated collection.
2173 }
2174 if ( !targetClass ) {
2175 Error("InitInfo", "Branch '%s': missing dictionary for target class '%s'!",
2177 return;
2178 }
2179 } else {
2180 targetClass = cl;
2181 }
2182 if (cl) {
2183 //---------------------------------------------------------------------
2184 // Get the streamer info for given version
2185 ///////////////////////////////////////////////////////////////////////
2186
2187 {
2188 if ( (cl->Property() & kIsAbstract) && cl == targetClass) {
2189 TBranchElement *parent = static_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
2190 if (parent && parent != this && !parent->GetClass()->IsLoaded() ) {
2191 // Our parent's class is emulated and we represent an abstract class.
2192 // and the target class has not been set explicitly.
2193 TString target = cl->GetName();
2194 target += "@@emulated";
2196
2197 if (!fTargetClass) {
2199 }
2201 }
2202 }
2203 if( targetClass != cl ) {
2204 fInfo = static_cast<TStreamerInfo*>(targetClass->GetConversionStreamerInfo( cl, fClassVersion ));
2205 } else {
2206 fInfo = static_cast<TStreamerInfo*>(cl->GetStreamerInfo(fClassVersion));
2207 }
2208 }
2209
2210 // FIXME: Check that the found streamer info checksum matches our branch class checksum here.
2211 // Check to see if the class code was unloaded/reloaded
2212 // since we were created.
2214 if (fCheckSum && (cl->IsForeign() || (!cl->IsLoaded() && (fClassVersion == 1) && cl->GetStreamerInfos()->At(1) && (fCheckSum != static_cast<TVirtualStreamerInfo*>(cl->GetStreamerInfos()->At(1))->GetCheckSum())))) {
2215 // Try to compensate for a class that got unloaded on us.
2216 // Search through the streamer infos by checksum
2217 // and take the first match.
2218
2220 if( targetClass != cl )
2221 info = static_cast<TStreamerInfo*>(targetClass->FindConversionStreamerInfo( cl, fCheckSum ));
2222 else {
2223 info = static_cast<TStreamerInfo*>(cl->FindStreamerInfo( fCheckSum ));
2224 if (info) {
2225 // Now that we found it, we need to make sure it is initialize (Find does not initialize the StreamerInfo).
2226 info = static_cast<TStreamerInfo*>(cl->GetStreamerInfo(info->GetClassVersion()));
2227 }
2228 }
2229 if( info ) {
2230 fInfo = info;
2231 // We no longer reset the class version so that in case the user is passing us later
2232 // the address of a class that require (another) Conversion we can find the proper
2233 // StreamerInfo.
2234 // fClassVersion = fInfo->GetClassVersion();
2235 }
2236 }
2237 }
2238}
2239
2240
2241////////////////////////////////////////////////////////////////////////////////
2242/// Init the streamer info for the branch class, try to compensate for class
2243/// code unload/reload and schema evolution.
2244
2246{
2247 if (!fInfo)
2248 SetupInfo();
2249
2250 //
2251 // Fixup cached streamer info if necessary.
2252 //
2253 // FIXME: What if the class code was unloaded/reloaded since we were cached?
2254
2255 if (fInfo) {
2256
2257 if (!fInfo->IsCompiled()) {
2258 // Streamer info has not yet been compiled.
2259
2260 Error("InitInfo","StreamerInfo is not compiled.");
2261 }
2262 // return immediately if we are called recursively.
2263 if (fInInitInfo)
2264 return;
2265 fInInitInfo = true;
2266 if (!fInit) {
2267 // We were read in from a file, figure out what our fID should be,
2268 // schema evolution must be considered.
2269 //
2270 // Force our fID to be the id of the first streamer element that matches our name.
2271 //
2272 auto SetOnfileObject = [this](TStreamerInfo *info) {
2273 Int_t arrlen = 1;
2274 if (fType==31 || fType==41) {
2275 TLeaf *leaf = static_cast<TLeaf*>(fLeaves.At(0));
2276 if (leaf) {
2277 arrlen = leaf->GetMaximum();
2278 }
2279 }
2280 bool toplevel = (fType == 3 || fType == 4 || (fType == 0 && fID == -2));
2281 bool seenExisting = false;
2282
2283 fOnfileObject = new TVirtualArray( info->GetElement(0)->GetClassPointer(), arrlen );
2284 // Propagate this to all the other branches belonging to the same object.
2286 Int_t nbranches = branches->GetEntriesFast();
2287 TBranchElement *lastbranch = this;
2288
2291 if (toplevel) {
2292 // Note: Fragile/wrong when using conversion StreamerInfo?
2293 currentClass = info->GetClass();
2294 currentVersion = info->GetClassVersion();
2295 }
2296
2297 // First find the first branch corresponding to the same class as 'this'
2298 // branch
2299 Int_t index = branches->IndexOf(this);
2300 Int_t firstindex = 0;
2302 if (index >= 0) {
2303 TString fullname( GetFullName() );
2304 Ssiz_t lastdot = fullname.Last('.');
2305 if (lastdot == TString::kNPOS) {
2306 // No prefix or index, thus this is a first level branch
2307 TBranchElement* subbranch = static_cast<TBranchElement*>(branches->At(0));
2308 if (!subbranch->fInfo)
2309 subbranch->SetupInfo();
2310 } else {
2311 TString &thisprefix = fullname.Remove(lastdot + 1); // Mod fullname and 'rename' the variable.
2312 for(Int_t i = index - 1; i >= 0; --i) {
2313 TBranchElement* subbranch = static_cast<TBranchElement*>(branches->At(i));
2314 TString subbranch_name(subbranch->GetFullName());
2315 if ( ! subbranch_name.BeginsWith(thisprefix)) {
2316 // We moved to another data member (of the enclosing class)
2317 firstindex = i + 1;
2318 break;
2319 }
2320 if (!subbranch->fInfo)
2321 subbranch->SetupInfo();
2322 }
2323 for(Int_t i = index; i < nbranches; ++i) {
2324 TBranchElement* subbranch = static_cast<TBranchElement*>(branches->At(i));
2325 TString subbranch_name(subbranch->GetFullName());
2326 if ( ! subbranch_name.BeginsWith(thisprefix)) {
2327 lastindex = i - 1;
2328 break;
2329 }
2330 }
2331 }
2332 } else {
2333 // Case of a top level branch or 'empty node' (object marker for split sub-object)
2334 TString fullname( GetFullName() );
2335 Ssiz_t lastdot = fullname.Last('.');
2336 if (lastdot != TString::kNPOS) {
2337 TString &thisprefix = fullname.Remove(lastdot + 1); // Mod fullname and 'rename' the variable.
2338 for(Int_t i = 0; i < nbranches; ++i) {
2339 TBranchElement* subbranch = static_cast<TBranchElement*>(branches->At(i));
2340 TString subbranch_name(subbranch->GetFullName());
2341 if ( ! subbranch_name.BeginsWith(thisprefix)) {
2342 lastindex = i - 1;
2343 break;
2344 }
2345 }
2346 }
2347 }
2348 for (Int_t i = firstindex; i <= lastindex; ++i) {
2349 TBranchElement* subbranch = static_cast<TBranchElement*>(branches->At(i));
2350 bool match = false;
2351 if (this != subbranch) {
2352
2353 if (!subbranch->fInfo)
2354 subbranch->SetupInfo();
2355
2356 if (subbranch->fInfo == info)
2357 match = true;
2358 else if (subbranch->fInfo == nullptr && subbranch->fBranchClass == currentClass) {
2359 if (!toplevel) {
2360 if (subbranch->fCheckSum == fCheckSum)
2361 match = true;
2362 } else {
2363 if (!subbranch->fBranchClass->IsForeign() && subbranch->fClassVersion == currentVersion)
2364 match = true;
2365 else if (subbranch->fCheckSum == info->GetCheckSum()) {
2366 match = true;
2367 }
2368 }
2369 }
2370 }
2371 if (match) {
2372 if (subbranch->fOnfileObject && subbranch->fOnfileObject != fOnfileObject) {
2373 if (seenExisting) {
2374 Error("SetOnfileObject (lambda)", "2 distincts fOnfileObject are in the hierarchy of %s for type %s",
2375 toplevel ? GetName() : GetMother()->GetSubBranch(this)->GetName(), info->GetName());
2376 } else {
2377 delete fOnfileObject;
2378 fOnfileObject = subbranch->fOnfileObject;
2379 seenExisting = true;
2380 }
2381 }
2382 subbranch->fOnfileObject = fOnfileObject;
2384 }
2385 }
2386 if (toplevel) {
2388 if (lastbranch != this)
2389 lastbranch->ResetBit(kOwnOnfileObj);
2390 } else {
2391 lastbranch->SetBit(kOwnOnfileObj);
2392 }
2393 };
2394 if (GetID() > -1) {
2395 // We are *not* a top-level branch.
2396 std::string s(GetName());
2397 size_t pos = s.rfind('.');
2398 if (pos != std::string::npos) {
2399 s = s.substr(pos+1);
2400 }
2401 while ((pos = s.rfind('[')) != std::string::npos) {
2402 s = s.substr(0, pos);
2403 }
2404 int offset = 0;
2407 size_t ndata = fInfo->GetNelement();
2408 fNewIDs.clear();
2409 for (size_t i = 0; i < ndata; ++i) {
2410 if (fInfo->GetElement(i) == elt) {
2411 if (elt->TestBit (TStreamerElement::kCache)
2412 && (i+1) < ndata
2413 && s == fInfo->GetElement(i)->GetName())
2414 {
2415 // If the TStreamerElement we found is storing the information in the
2416 // cache and is a repeater, we need to use the real one (the next one).
2417 // (At least until the cache/repeat mechanism is properly handle by
2418 // ReadLeaves).
2419 // fID = i+1;
2420 fID = i;
2421 if (fType != 2) {
2422 if (elt->TestBit(TStreamerElement::kRepeat)) {
2423 fNewIDs.push_back(fID+1);
2424 fNewIDs.back().fElement = fInfo->GetElement(i+1);
2425 fNewIDs.back().fInfo = fInfo;
2426 } else if (fInfo->GetElement(i+1)->TestBit(TStreamerElement::kWrite)) {
2427 fNewIDs.push_back(fID+1);
2428 fNewIDs.back().fElement = fInfo->GetElement(i+1);
2429 fNewIDs.back().fInfo = fInfo;
2430 }
2431 }
2432 } else {
2433 fID = i;
2434 }
2435 if (elt->TestBit (TStreamerElement::kCache)) {
2437 }
2438 break;
2439 }
2440 }
2441 for (size_t i = fID+1+(fNewIDs.size()); i < ndata; ++i) {
2443
2444 std::string ename = nextel->GetName();
2445 if (ename[0] == '*')
2446 ename = ename.substr(1);
2447
2448 while ((pos = ename.rfind('[')) != std::string::npos) {
2449 ename = ename.substr(0, pos);
2450 }
2451
2452 if (s != ename) {
2453 // We moved on to the next set
2454 break;
2455 }
2456 // Add all (and only) the Artificial Elements that follows this StreamerInfo.
2457 // fprintf(stderr,"%s/%d[%zu] passing through %zu %s\n",GetName(),fID,fIDs.size(),i,nextel->GetName());
2458 if (fType==31||fType==41) {
2459 // The nested objects are unfolded and their branch can not be used to
2460 // execute StreamerElements of this StreamerInfo.
2461 if ((nextel->GetType() == TStreamerInfo::kObject
2462 || nextel->GetType() == TStreamerInfo::kAny)
2463 && nextel->GetClassPointer()->CanSplit())
2464 {
2465 continue;
2466 }
2467 }
2468 if (nextel->GetOffset() == TStreamerInfo::kMissing) {
2469 // This element will be 'skipped', it's TBranchElement's fObject will null
2470 // and thus can not be used to execute the artificial StreamerElements
2471 continue;
2472 }
2473 if (nextel->IsA() != TStreamerArtificial::Class()
2474 || nextel->GetType() == TStreamerInfo::kCacheDelete ) {
2475 continue;
2476 }
2477 // NOTE: We should verify that the rule's source are 'before'
2478 // or 'at' this branch.
2479 // fprintf(stderr,"%s/%d[%zu] pushd %zu %s\n",GetName(),fID,fIDs.size(),i,nextel->GetName());
2480 fNewIDs.push_back(i);
2481 fNewIDs.back().fElement = nextel;
2482 fNewIDs.back().fInfo = fInfo;
2483 }
2484 } else if (elt && offset==TStreamerInfo::kMissing) {
2485 // Still re-assign fID properly.
2486 fNewIDs.clear();
2487 size_t ndata = fInfo->GetNelement();
2488 for (size_t i = 0; i < ndata; ++i) {
2489 if (fInfo->GetElement(i) == elt) {
2490 fID = i;
2491 break;
2492 }
2493 }
2494 } else {
2495 // We have not even found the element .. this is strange :(
2496 // fNewIDs.clear();
2497 // fID = -3;
2498 // SetBit(kDoNotProcess);
2499 }
2500 if (fOnfileObject==nullptr && (fType==31 || fType==41 || (0 <= fType && fType <=2) ) && fInfo->GetNelement()
2502 {
2504 }
2505 }
2506 if (fType == 3 || fType == 4 || (fType == 0 && fID == -2) || fType == 2) {
2507 // Need to add the rule targeting transient members.
2509 if (fType == 3 || fType == 4) {
2510 // Don't we have real version information?
2511 // Not unless there is a subbranch with a non-split element of the class.
2512 // Search for the correct version.
2514 }
2515
2516 TString prefix(GetFullName());
2517 if (fType == 2 && fID >= 0) {
2518 auto start = prefix.Length();
2519 if (prefix[start - 1] == '.')
2520 --start;
2521 std::string_view view(prefix.Data(), start);
2522 auto cutoff = view.find_last_of('.');
2523 if (cutoff != std::string::npos) {
2524 prefix.Remove(cutoff + 1);
2525 }
2526 }
2527 if (prefix[prefix.Length()-1] != '.') {
2528 if (fType == 3 || fType == 4 || prefix.Index('.') != TString::kNPOS) {
2529 prefix += ".";
2530 } else {
2531 prefix = "";
2532 }
2533 }
2534 fNewIDs.clear();
2535
2537
2538 if (!fNewIDs.empty() && fOnfileObject == nullptr && localInfo->GetElement(0)->GetType() == TStreamerInfo::kCacheNew)
2539 {
2541 }
2542
2543 }
2544 fInit = true;
2545
2546 // Get the action sequence we need to copy for reading.
2549 } else if (!fReadActionSequence) {
2550 // Get the action sequence we need to copy for reading.
2553 }
2556 fInInitInfo = false;
2557 }
2558}
2559
2560////////////////////////////////////////////////////////////////////////////////
2561/// Return the collection proxy describing the branch content, if any.
2562
2564{
2565 if (fCollProxy) {
2566 return fCollProxy;
2567 }
2568 TBranchElement* thiscast = const_cast<TBranchElement*>(this);
2569 if (fType == 4) {
2570 // STL container top-level branch.
2571 const char* className = nullptr;
2572 TClass* cl = nullptr;
2573 if (fID < 0) {
2574 // We are a top-level branch.
2575 if (fBranchClass.GetClass()) {
2576 cl = fBranchClass.GetClass();
2577 }
2578 } else {
2579 // We are not a top-level branch.
2580 TVirtualStreamerInfo* si = thiscast->GetInfoImp();
2581 if (fCollProxy) {
2582 // The GetInfo set fProxy for us, let's not
2583 // redo it; the value of fCollProxy is possibly
2584 // used/recorded is the actions sequences, so
2585 // if we change it here, we would need to propagate
2586 // the change.
2587 return fCollProxy;
2588 }
2589 TStreamerElement* se = si->GetElement(fID);
2590 cl = se->GetClassPointer();
2591 }
2592 if (!cl) {
2593 // The TClass was not created but we do know (since it
2594 // is used as a collection) that it 'className' was a
2595 // class, so let's create it by hand!.
2596
2597 if (fID < 0) {
2599 className = cl->GetName();
2600 } else {
2601 cl = new TClass(className, fClassVersion);
2602 className = cl->GetName();
2603 }
2604 }
2606 if (!proxy) {
2607 // humm, we must have an older file with a custom collection
2608 // let's try to work-around it.
2609 TString equiv;
2610 equiv.Form("vector<%s>",fClonesName.Data());
2612 proxy = clequiv->GetCollectionProxy();
2613 if (!proxy) {
2614 Fatal("GetCollectionProxy",
2615 "Can not create a Collection Proxy of any kind for the class \"%s\" needed by the branch \"%s\" of the TTree \"%s\"!",
2616 className, GetName(), GetTree()->GetName());
2617 }
2618 if (gDebug > 0) Info("GetCollectionProxy",
2619 "Fixing the collection proxy of the class \"%s\" \n"
2620 "\tneeded by the branch \"%s\" of the TTree \"%s\" to be similar to \"%s\".",
2621 className, GetName(), GetTree()->GetName(),equiv.Data());
2622 cl->CopyCollectionProxy( *proxy );
2623 }
2624 fCollProxy = proxy->Generate();
2625 fSTLtype = proxy->GetCollectionType();
2626 } else if (fType == 41) {
2627 // STL container sub-branch.
2628 thiscast->fCollProxy = fBranchCount->GetCollectionProxy();
2629 }
2630 return fCollProxy;
2631}
2632
2633////////////////////////////////////////////////////////////////////////////////
2634/// Return a pointer to the current type of the data member corresponding to branch element.
2635
2637{
2638 TClass* cl = fCurrentClass;
2639 if (cl) {
2640 return cl;
2641 }
2642
2643 TStreamerInfo* brInfo = static_cast<TStreamerInfo*>(GetInfoImp());
2644 if (!brInfo) {
2646 R__ASSERT(cl && cl->GetCollectionProxy());
2647 fCurrentClass = cl;
2648 return cl;
2649 }
2650 TClass* motherCl = brInfo->GetClass();
2651 if (motherCl->GetCollectionProxy()) {
2652 cl = motherCl->GetCollectionProxy()->GetCollectionClass();
2653 if (cl) {
2654 fCurrentClass = cl;
2655 }
2656 return cl;
2657 }
2658 if (GetID() < 0 || GetID()>=brInfo->GetNelement()) {
2659 return nullptr;
2660 }
2662 TDataMember* dm = static_cast<TDataMember*>(motherCl->GetListOfDataMembers()->FindObject(currentStreamerElement->GetName()));
2663
2665 if (!dm) {
2666 // Either the class is not loaded or the data member is gone
2667 if (!motherCl->IsLoaded()) {
2668 TVirtualStreamerInfo* newInfo = motherCl->GetStreamerInfo();
2669 if (newInfo != brInfo) {
2670 TStreamerElement* newElems = static_cast<TStreamerElement*>(newInfo->GetElements()->FindObject(currentStreamerElement->GetName()));
2671 if (newElems) {
2672 if (newElems->GetClassPointer())
2673 newType = newElems->GetClassPointer()->GetName();
2674 else
2675 newType = newElems->GetTypeName();
2676 }
2677 }
2678 if (newType.Length()==0) {
2679 if (currentStreamerElement->GetClassPointer())
2680 newType = currentStreamerElement->GetClassPointer()->GetName();
2681 else
2682 newType = currentStreamerElement->GetTypeName();
2683 }
2684 }
2685 } else {
2686 newType = dm->GetTypeName();
2687 }
2689 if (cl) {
2690 fCurrentClass = cl;
2691 }
2692 return cl;
2693}
2694
2695////////////////////////////////////////////////////////////////////////////////
2696/// Read all branches of a BranchElement and return total number of bytes.
2697///
2698/// - If entry = 0, then use current entry number + 1.
2699/// - If entry < 0, then reset entry number to 0.
2700///
2701/// Returns the number of bytes read from the input buffer.
2702/// - If entry does not exist, then returns 0.
2703/// - If an I/O error occurs, then returns -1.
2704///
2705/// See IMPORTANT REMARKS in TTree::GetEntry.
2706
2708{
2709 // Remember which entry we are reading.
2710 auto prevEntry = fReadEntry;
2711 fReadEntry = entry;
2712
2713 // If our tree has a branch ref, make it remember the entry and
2714 // this branch. This allows a TRef::GetObject() call done during
2715 // the following I/O operation, for example in a custom streamer,
2716 // to search for the referenced object in the proper element of the
2717 // proper branch.
2719 if (R__unlikely(bref)) {
2720 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
2721 fBranchID = bref->SetParent(this, fBranchID);
2722 bref->SetRequestedEntry(entry);
2723 }
2724
2725 Int_t nbytes = 0;
2726
2727 if (R__unlikely(IsAutoDelete())) {
2730 } else {
2732 R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
2734 }
2735 }
2736
2738 if (nbranches) {
2739 // -- Branch has daughters.
2740 // One must always read the branch counter.
2741 // In the case when one reads consecutively twice the same entry,
2742 // the user may have cleared the TClonesArray between the GetEntry calls.
2743 if ((fType == 3) || (fType == 4)) {
2745 if (nb < 0) {
2746 return nb;
2747 }
2748 nbytes += nb;
2749 }
2751 ValidateAddress(); // There is no ReadLeave for the node of a top level split object, so we need to do the
2752 // validation here.
2753 for (Int_t i = 0; i < nbranches; ++i) {
2754 TBranch* branch = static_cast<TBranch*>(fBranches.UncheckedAt(i));
2755 Int_t nb = branch->GetEntry(entry, getall);
2756 if (nb < 0) {
2757 return nb;
2758 }
2759 nbytes += nb;
2760 }
2761 }
2763 if (fType == 3) {
2764 // Apply the unattached rules; by definition they do not need any
2765 // input from a buffer.
2767
2768 auto ndata = GetNdata();
2769
2770 TClonesArray* clones = reinterpret_cast<TClonesArray*>(fObject);
2771 if (clones->IsZombie()) {
2772 return -1;
2773 }
2774 R__PushCache onfileObject(b, fOnfileObject, ndata);
2775
2776 char **arr = reinterpret_cast<char **>(clones->GetObjectRef());
2777 char **end = arr + fNdata;
2778
2779 b.ApplySequenceVecPtr(*fReadActionSequence,arr,end);
2780 } else if (fType == 4) {
2781 // Apply the unattached rules; by definition they do not need any
2782 // input from a buffer.
2784
2785 auto ndata = GetNdata();
2786
2787 R__PushCache onfileObject(b, fOnfileObject, ndata);
2790
2792 b.ApplySequence(*fReadActionSequence,iter->fBegin,iter->fEnd);
2793 } else {
2794 // Apply the unattached rules; by definition they do not need any
2795 // input from a buffer.
2797 R__PushCache onfileObject(b, fOnfileObject, fNdata);
2798 b.ApplySequence(*fReadActionSequence, fObject);
2799 }
2800 }
2801 } else {
2802 // -- Terminal branch.
2803
2805 Int_t nb = fBranchCount->TBranch::GetEntry(entry, getall);
2806 if (nb < 0)
2807 return nb;
2808 nbytes += nb;
2809 }
2810 // For associative containers, the count branch is actually
2811 // reading the subbranches (including this one) and in the case
2812 // of a compiled proxy the necessary staging area is only available
2813 // during the call to the count branch GetEntry.
2814 // We detect this code path by checking the position of the cursor,
2815 // which is explicitly reset by the count branch's GetEntry.
2816 // One down-side, if the user call twice GetEntry on the same entry,
2817 // the second call will not re-read the sub-branches (unlike all the other
2818 // types of branches).
2821 if (nb < 0) {
2822 return nb;
2823 }
2824 nbytes += nb;
2825 }
2826 }
2827
2828 if (R__unlikely(fTree->Debug() > 0)) {
2829 if ((entry >= fTree->GetDebugMin()) && (entry <= fTree->GetDebugMax())) {
2830 Info("GetEntry", "%lld, branch=%s, nbytes=%d", entry, GetName(), nbytes);
2831 }
2832 }
2833 return nbytes;
2834}
2835
2836////////////////////////////////////////////////////////////////////////////////
2837/// Fill expectedClass and expectedType with information on the data type of the
2838/// object/values contained in this branch (and thus the type of pointers
2839/// expected to be passed to Set[Branch]Address
2840/// return 0 in case of success and > 0 in case of failure.
2841
2843{
2844 expectedClass = nullptr;
2846
2848 if ((type == -1) || (fID == -1)) {
2850 } else {
2851 // Case of an object data member. Here we allow for the
2852 // variable name to be omitted. Eg, for Event.root with split
2853 // level 1 or above Draw("GetXaxis") is the same as Draw("fH.GetXaxis()")
2855 if (element) {
2856 expectedClass = element->GetClassPointer();
2857 if (!expectedClass) {
2858 TDataType* data = gROOT->GetType(element->GetTypeNameBasic());
2859 if (!data) {
2860 Error("GetExpectedType", "Did not find the type number for %s", element->GetTypeNameBasic());
2861 return 1;
2862 } else {
2863 expectedType = (EDataType) data->GetType();
2864 }
2865 }
2866 } else {
2867 Error("GetExpectedType", "Did not find the type for %s",GetName());
2868 return 2;
2869 }
2870 }
2871 return 0;
2872}
2873
2874////////////////////////////////////////////////////////////////////////////////
2875/// Return the 'full' name of the branch. In particular prefix the mother's name
2876/// when it does not end in a trailing dot and thus is not part of the branch name
2878{
2879 TBranchElement* mother = static_cast<TBranchElement*>(GetMother());
2880 if (!mother || mother==this || mother->GetType() == 3 || mother->GetType() == 4) {
2881 // The parent's name is already included in the name for split TClonesArray and STL collections
2882 return fName;
2883 }
2884
2885 return TBranch::GetFullName();
2886}
2887
2888////////////////////////////////////////////////////////////////////////////////
2889/// Return icon name depending on type of branch element.
2890
2892{
2893 if (IsFolder()) {
2894 return "TBranchElement-folder";
2895 } else {
2896 return "TBranchElement-leaf";
2897 }
2898}
2899
2900////////////////////////////////////////////////////////////////////////////////
2901/// Return whether this branch is in a mode where the object are decomposed
2902/// or not (Also known as MakeClass mode).
2903
2905{
2906 return TestBit(kDecomposedObj); // Same as TestBit(kMakeClass)
2907}
2908
2909////////////////////////////////////////////////////////////////////////////////
2910/// Return maximum count value of the branchcount if any.
2911
2913{
2914 if (fBranchCount) {
2915 return fBranchCount->GetMaximum();
2916 }
2917 return fMaximum;
2918}
2919
2920////////////////////////////////////////////////////////////////////////////////
2921/// Return a pointer to our object.
2922
2924{
2926 return fObject;
2927}
2928
2929////////////////////////////////////////////////////////////////////////////////
2930/// Return a pointer to the parent class of the branch element.
2931
2936
2937////////////////////////////////////////////////////////////////////////////////
2938/// Return type name of element in the branch.
2939
2941{
2942 if (fType == 3 || fType == 4) {
2943 return "Int_t";
2944 }
2945 // FIXME: Use symbolic constants here.
2946 if ((fStreamerType < 1) || (fStreamerType > 59)) {
2947 if (fBranchClass.GetClass()) {
2948 if (fID>=0) {
2949 return GetInfoImp()->GetElement(fID)->GetTypeName();
2950 } else {
2951 return fBranchClass.GetClass()->GetName();
2952 }
2953 } else {
2954 return nullptr;
2955 }
2956 }
2957 const char *types[20] = {
2958 "",
2959 "Char_t",
2960 "Short_t",
2961 "Int_t",
2962 "Long_t",
2963 "Float_t",
2964 "Int_t",
2965 "char*",
2966 "Double_t",
2967 "Double32_t",
2968 "",
2969 "UChar_t",
2970 "UShort_t",
2971 "UInt_t",
2972 "ULong_t",
2973 "UInt_t",
2974 "Long64_t",
2975 "ULong64_t",
2976 "Bool_t",
2977 "Float16_t"
2978 };
2979 Int_t itype = fStreamerType % 20;
2980 return types[itype];
2981}
2982
2983////////////////////////////////////////////////////////////////////////////////
2984
2988
2989template <typename T>
2991{
2992 // -- Returns the branch value.
2993 //
2994 // If the leaf is an array, j is the index in the array.
2995 //
2996 // If leaf is an array inside a TClonesArray, len should be the length
2997 // of the array.
2998 //
2999 // If subarr is true, then len is actually the index within the sub-array.
3000 //
3001
3003
3004 Int_t prID = fID;
3005 char *object = fObject;
3006 if (TestBit(kCache)) {
3007 if (GetInfoImp()->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
3008 prID = fID+1;
3009 } else if (fOnfileObject) {
3010 object = fOnfileObject->GetObjectAt(0);
3011 }
3012 }
3013
3014 if (!j && fBranchCount) {
3016 // Since reloading the index, will reset the ClonesArray, let's
3017 // skip the load if we already read this entry.
3018 if (entry != fBranchCount->GetReadEntry()) {
3019 fBranchCount->TBranch::GetEntry(entry);
3020 }
3022 fBranchCount2->TBranch::GetEntry(entry);
3023 }
3024 }
3025
3026 if (TestBit(kDecomposedObj)) {
3027 if (!fAddress) {
3028 return 0;
3029 }
3030 if ((fType == 3) || (fType == 4)) {
3031 // Top-level branch of a TClonesArray.
3032 return fNdata;
3033 } else if ((fType == 31) || (fType == 41)) {
3034 // sub branch of a TClonesArray
3036 if (atype < 20) {
3037 atype += 20;
3038 }
3039 return GetInfoImp()->GetTypedValue<T>(fAddress, atype, j, 1);
3040 } else if (fType <= 2) {
3041 // branch in split mode
3042 // FIXME: This should probably be < 60 instead!
3043 if ((fStreamerType > 40) && (fStreamerType < 55)) {
3044 Int_t atype = fStreamerType - 20;
3045 return GetInfoImp()->GetTypedValue<T>(fAddress, atype, j, 1);
3046 } else {
3047 return GetInfoImp()->GetTypedValue<T>(object, prID, j, -1);
3048 }
3049 }
3050 }
3051
3052 if (object == nullptr)
3053 {
3054 // We have nowhere to read the data from (probably because the data member was
3055 // 'dropped' from the current schema).
3056 return 0;
3057 }
3058
3059 if (fType == 31) {
3060 TClonesArray* clones = reinterpret_cast<TClonesArray*>(object);
3061 if (subarr) {
3063 }
3065 } else if (fType == 41) {
3068 {
3069 if (subarr)
3070 return GetInfoImp()->GetTypedValueSTL<T>(const_cast<TBranchElement*>(this)->GetCollectionProxy(), prID, j, len, fOffset);
3071
3072 return GetInfoImp()->GetTypedValueSTL<T>(const_cast<TBranchElement*>(this)->GetCollectionProxy(), prID, j/len, j%len, fOffset);
3073 }
3074 else
3075 {
3076 if (subarr)
3077 return GetInfoImp()->GetTypedValueSTLP<T>(const_cast<TBranchElement*>(this)->GetCollectionProxy(), prID, j, len, fOffset);
3078 return GetInfoImp()->GetTypedValueSTLP<T>(const_cast<TBranchElement*>(this)->GetCollectionProxy(), prID, j/len, j%len, fOffset);
3079 }
3080 } else {
3081 auto info = GetInfoImp();
3082 if (info) {
3083 return info->GetTypedValue<T>(object, prID, j, -1);
3084 }
3085 return 0;
3086 }
3087}
3088
3089////////////////////////////////////////////////////////////////////////////////
3090/// Returns pointer to first data element of this branch.
3091/// Currently used only for members of type character.
3092
3094{
3096
3097 TStreamerInfo *info = nullptr;
3098 Int_t prID = fID;
3099 char *object = fObject;
3100 if (TestBit(kCache)) {
3101 info = GetInfoImp();
3102 if (info->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
3103 prID = fID+1;
3104 } else if (fOnfileObject) {
3105 object = fOnfileObject->GetObjectAt(0);
3106 }
3107 }
3108
3109 if (fBranchCount) {
3111 fBranchCount->TBranch::GetEntry(entry);
3112 if (fBranchCount2) fBranchCount2->TBranch::GetEntry(entry);
3113 }
3114 if (TestBit(kDecomposedObj)) {
3115 if (!fAddress) {
3116 return nullptr;
3117 }
3118 if (fType == 3) { //top level branch of a TClonesArray
3119 //return &fNdata;
3120 return nullptr;
3121 } else if (fType == 4) { //top level branch of a TClonesArray
3122 //return &fNdata;
3123 return nullptr;
3124 } else if (fType == 31) { // sub branch of a TClonesArray
3125 //Int_t atype = fStreamerType;
3126 //if (atype < 20) atype += 20;
3127 //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
3128 return nullptr;
3129 } else if (fType == 41) { // sub branch of a TClonesArray
3130 //Int_t atype = fStreamerType;
3131 //if (atype < 20) atype += 20;
3132 //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
3133 return nullptr;
3134 } else if (fType <= 2) { // branch in split mode
3135 // FIXME: This should probably be < 60 instead!
3136 if (fStreamerType > 40 && fStreamerType < 55) {
3137 //Int_t atype = fStreamerType - 20;
3138 //return GetInfoImp()->GetValue(fAddress, atype, j, 1);
3139 return nullptr;
3140 } else {
3141 //return GetInfoImp()->GetValue(object, fID, j, -1);
3142 return nullptr;
3143 }
3144 }
3145 }
3146
3147 if (fType == 31) {
3148 return nullptr;
3149 } else if (fType == 41) {
3150 return nullptr;
3151 } else if (prID < 0) {
3152 return object;
3153 } else {
3154 //return GetInfoImp()->GetValue(object,fID,j,-1);
3155 if (!info)
3156 info = GetInfoImp();
3157 if (!info || !object) return nullptr;
3158 char **val = reinterpret_cast<char **>(object+info->TStreamerInfo::GetElementOffset(prID));
3159 return *val;
3160 }
3161}
3162
3163////////////////////////////////////////////////////////////////////////////////
3164/// Initialize the base class subobjects offsets of our sub-branches and set fOffset if we are a container sub-branch.
3165///
3166/// Note: The offsets are zero for data members so that when
3167/// SetAddress recursively sets their address, they will get the
3168/// same address as their containing class because i/o is based
3169/// on streamer info offsets from the address of the containing
3170/// class.
3171///
3172/// Offsets are non-zero for base-class sub-branches that are
3173/// not the leftmost direct base class. They are laid out in
3174/// memory sequentially and only the leftmost direct base class
3175/// has the same address as the derived class. The streamer
3176/// offsets need to be added to the address of the base class
3177/// subobject which is not the same as the address of the
3178/// derived class for the non-leftmost direct base classes.
3179
3181{
3183
3184 // See https://sft.its.cern.ch/jira/browse/ROOT-8742
3185 // and https://sft.its.cern.ch/jira/browse/ROOT-9253
3186 // As of commit e21b4f1a3b, removing this lock lead to a failure
3187 // in the test testSetAddress[Loop].
3188 // As of commit 4f8b237849, removing this lock does not lead to
3189 // a visible failure in test. This might be due to the underlying
3190 // problem (missing lock or ?) being solved somewhere else or some
3191 // other perturbation reducing the failure rate.
3192 // Having the lock here is not too costly as InitializeOffsets is
3193 // one called once in the lifetime of the TBranch.
3195
3196 if (fID < 0) {
3197 // -- We are a top-level branch. Let's mark whether we need to use MapObject.
3199 if (fBranchClass.GetClass()->IsTObject()) {
3201 } else {
3203 }
3204 }
3205 }
3206 if (nbranches) {
3207 // Allocate space for the new sub-branch offsets.
3208 delete[] fBranchOffset;
3209 fBranchOffset = nullptr;
3211 // Make sure we can instantiate our class meta info.
3212 if (!fBranchClass.GetClass()) {
3213 Warning("InitializeOffsets", "No branch class set for branch: %s", GetName());
3214 fInitOffsets = true;
3215 return;
3216 }
3217 // Make sure we can instantiate our class streamer info.
3219 if (!info) {
3220 Warning("InitializeOffsets", "No streamer info available for branch: %s of class: %s", GetName(), fBranchClass.GetClass()->GetName());
3221 fInitOffsets = true;
3222 return;
3223 }
3224
3225 // Get the class we are a member of now (which is the
3226 // type of our containing subobject) and get our offset
3227 // inside of our containing subobject (our local offset).
3228 // Note: branchElem stays zero if we are a top-level branch,
3229 // we have to be careful about this later.
3230 TStreamerElement* branchElem = nullptr;
3231 Int_t localOffset = 0;
3233 bool renamed = false;
3234 if (fID > -1) {
3235 // -- Branch is *not* a top-level branch.
3236 // Instead of the streamer info class, we want the class of our
3237 // specific element in the streamer info. We could be a data
3238 // member of a base class or a split class, in which case our
3239 // streamer info will be for our containing sub-object, while
3240 // we are actually a different type.
3241 // Note: We tested to make sure the streamer info was available previously.
3242 if (!info->IsCompiled()) {
3243 Warning("InitializeOffsets", "Streamer info for branch: %s has no elements array!", GetName());
3244 fInitOffsets = true;
3245 return;
3246 }
3247 // FIXME: Check that fID is in range.
3248 branchElem = info->GetElement(fID);
3249 if (!branchElem) {
3250 Warning("InitializeOffsets", "Cannot get streamer element for branch: %s!", GetName());
3251 fInitOffsets = true;
3252 return;
3253 } else if (branchElem->TestBit(TStreamerElement::kRepeat)) {
3254 // If we have a repeating streamerElement, use the next
3255 // one as it actually hold the 'real' data member('s offset)
3256 if (info->GetElement(fID+1)) {
3257 branchElem = info->GetElement(fID+1);
3258 }
3259 }
3260 localOffset = branchElem->GetOffset();
3261 branchClass = branchElem->GetClassPointer();
3263 fObject = nullptr;
3264 } else {
3265 renamed = branchClass && branchElem->GetNewClass() && (branchClass != branchElem->GetNewClass());
3266 }
3267 } else {
3269 }
3270 if (!branchClass) {
3271 Error("InitializeOffsets", "Could not find class for branch: %s", GetName());
3272 fInitOffsets = true;
3273 return;
3274 }
3275
3276 //------------------------------------------------------------------------
3277 // Extract the name of the STL branch in case it has been split.
3278 //////////////////////////////////////////////////////////////////////////
3279
3281 bool stlParentNameUpdated = false;
3282 if( fType == 4 )
3283 {
3284 TBranch *br = GetMother()->GetSubBranch( this );
3285 stlParentName = br->GetName();
3287
3288 // We may ourself contain the 'Mother' branch name.
3289 // To avoid code duplication, we delegate the removal
3290 // of the mother's name to the first sub-branch loop.
3291 }
3292
3293 // Loop over our sub-branches and compute their offsets.
3295 bool alternateElement = false;
3296
3299 if (subBranch == nullptr) {
3300 // -- Skip sub-branches that are not TBranchElements.
3301 continue;
3302 }
3303
3304 if (renamed) {
3305 if (subBranch->fBranchClass == branchClass) {
3306 if (branchElem) subBranch->SetTargetClass(branchElem->GetNewClass()->GetName());
3307 else subBranch->SetTargetClass(fTargetClass->GetName());
3308 }
3309 }
3310
3311 TVirtualStreamerInfo* sinfo = subBranch->GetInfoImp();
3312 if (!sinfo) {
3313 Warning("InitializeOffsets", "No streamer info for branch: %s subbranch: %s", GetName(), subBranch->GetName());
3315 continue;
3316 }
3317 if (!sinfo->IsCompiled()) {
3318 Warning("InitializeOffsets", "No elements array for branch: %s subbranch: %s", GetName(), subBranch->GetName());
3320 continue;
3321 }
3322 // FIXME: Make sure subBranch->fID is in range.
3323 TStreamerElement* subBranchElement = sinfo->GetElement(subBranch->fID);
3324 if (!subBranchElement) {
3325 Warning("InitializeOffsets", "No streamer element for branch: %s subbranch: %s", GetName(), subBranch->GetName());
3327 continue;
3328 } else if (subBranchElement->TestBit(TStreamerElement::kRepeat)) {
3329 // If we have a repeating streamerElement, use the next
3330 // one as it actually hold the 'real' data member('s offset)
3331 if (sinfo->GetElement(subBranch->fID+1)) {
3332 subBranchElement = sinfo->GetElement(subBranch->fID+1);
3333 }
3334 } else if (subBranchElement->TestBit(TStreamerElement::kCache)) {
3335 // We have a cached item which is not a repeated but we might still
3336 // have some Actions triggered by a rule that affect real
3337 // data member(s).
3338 if (subBranch->fReadActionSequence && subBranch->fReadActionSequence->fActions.size() > 1) {
3339 typedef TStreamerInfoActions::ActionContainer_t::iterator iterator;
3340 iterator end = subBranch->fReadActionSequence->fActions.end();
3341 for(iterator iter = subBranch->fReadActionSequence->fActions.begin();
3342 iter != end; ++iter) {
3343 TStreamerInfoActions::TConfiguration *config = iter->fConfiguration;
3344 UInt_t id = config->fElemId;
3345 TStreamerElement *e = static_cast<TStreamerElement*>(config->fInfo->GetElements()->At(id));
3346 if (e && !e->TestBit(TStreamerElement::kCache)) {
3348 alternateElement = true;
3349 break;
3350 }
3351 }
3352 }
3353 }
3354
3355 localOffset = subBranchElement->GetOffset();
3357 subBranch->fObject = nullptr;
3358 }
3359 {
3360 Int_t streamerType = subBranchElement->GetType();
3362 && subBranch->GetListOfBranches()->GetEntriesFast()==0
3363 && CanSelfReference(subBranchElement->GetClass()))
3364 {
3365 subBranch->SetBit(kBranchAny);
3366 } else {
3367 subBranch->ResetBit(kBranchAny);
3368 }
3369 }
3370
3371 if (subBranchElement->GetNewType()<0) {
3372 subBranch->ResetBit(kBranchAny);
3373 subBranch->ResetBit(kBranchObject);
3374 }
3375
3376 // Note: This call is expensive, do it only once.
3378 if (!mother) {
3379 Warning("InitializeOffsets", "Branch '%s' has no mother!", GetName());
3381 continue;
3382 }
3383 TString motherName(mother->GetName());
3384 bool motherDot = false;
3385 if (motherName.Length() && strchr(motherName.Data(), '.')) {
3386 motherDot = true;
3387 }
3388 bool motherDotAtEnd = false;
3389 if (motherName.Length() && (motherName[motherName.Length()-1] == '.')) {
3390 motherDotAtEnd = true;
3391 }
3392
3393 bool isBaseSubBranch = false;
3394 if ((subBranch->fType == 1) || (subBranchElement && subBranchElement->IsBase())) {
3395 // -- Base class sub-branch (1).
3396 //
3397 // Note: Our type will not be 1, even though we are
3398 // a base class branch, if we are not split (see the
3399 // constructor), or if we are an STL container master
3400 // branch and a base class branch at the same time
3401 // or an std::string.
3402 isBaseSubBranch = true;
3403 }
3404
3405 bool isContDataMember = false;
3406 if ((subBranch->fType == 31) || (subBranch->fType == 41)) {
3407 // -- Container data member sub-branch (31 or 41).
3408 isContDataMember = true;
3409 }
3410
3411 // I am either a data member sub-branch (0), or a base class
3412 // sub-branch (1), or TClonesArray master sub-branch (3),
3413 // or an STL container master sub-branch (4), or TClonesArray
3414 // data member sub-branch (31), or an STL container data member
3415 // sub-branch (41).
3416 //
3417 // My parent branch is either a top-level branch ((0), fID==(-2,-1)),
3418 // or a base class sub-branch (1), or a split-class branch (2),
3419 // or a TClonesArray master branch (3), or an STL container
3420 // master branch (4).
3421 //
3422
3423 //
3424 // We need to extract from our name the name
3425 // of the data member which contains us, so
3426 // that we may then do a by-name lookup in the
3427 // dictionary meta info of our parent class to
3428 // get our offset in our parent class.
3429 //
3430
3431 // Get our name.
3432 TString dataName(subBranch->GetName());
3433 if (motherDotAtEnd) {
3434 // -- Remove the top-level branch name from our name.
3435 dataName.Remove(0, motherName.Length());
3436 // stlParentNameUpdated is false the first time in this loop.
3437 if (!stlParentNameUpdated && stlParentName.Length()) {
3438 stlParentName.Remove(0, motherName.Length());
3439 stlParentNameUpdated = true;
3440 }
3441 } else if (fType == 4) {
3442 // This is a top-level branch of type STL collection. In this current
3443 // iteration, we are trying to calculate the offset of one of the
3444 // base classes of the element type of the STL collection. The
3445 // dataName string in this case will be akin to
3446 // "nameOfBranch.BaseClassName". Later logic in this function will
3447 // try to get the TRealData relative to "BaseClassName". But if the
3448 // base class is not splittable (i.e. it has a custom streamer), that
3449 // will not work anyway. The treatment of base classes follows a
3450 // different path: we remove the leading name of the branch, so only
3451 // the name of the base class is left. This will be later detected
3452 // and dataName will be stripped from the name of the base class,
3453 // leaving the string completely empty. Since the dataName string
3454 // will be empty, the logic of this function skips the part related
3455 // to finding the TRealData and directly computes the base class
3456 // offset.
3457 // Only perform the modification of the string if it looks as we
3458 // expect
3459 if (dataName == (motherName + '.' + subBranchElement->GetName()))
3460 dataName = subBranchElement->GetName();
3461 } else if (motherDot) {
3462 // -- Remove the top-level branch name from our name, folder case.
3463 //
3464 // Note: We are in the case where our mother was created
3465 // by the branch constructor which takes a folder
3466 // as an argument. The mother branch has internal
3467 // dots in its name to represent the folder hierarchy.
3468 // The TTree::Bronch() routine has handled us as a
3469 // special case, we must compensate.
3470 if ((fID < 0) && (subBranchElement->IsA() == TStreamerBase::Class())) {
3471 // -- Our name is the mother name, remove it.
3472 // Note: The test is our parent is a top-level branch
3473 // and our streamer is the base class streamer,
3474 // this matches the exact test in TTree::Bronch().
3475 if (dataName.Length() == motherName.Length()) {
3476 dataName.Remove(0, motherName.Length());
3477 // stlParentNameUpdated is false the first time in this loop.
3478 if (!stlParentNameUpdated && stlParentName.Length()) {
3479 stlParentName.Remove(0, motherName.Length());
3480 }
3481 }
3482 } else {
3483 // -- Remove the mother name and the dot.
3484 if (dataName.Length() > motherName.Length()) {
3485 dataName.Remove(0, motherName.Length() + 1);
3486 if (!stlParentNameUpdated && stlParentName.Length()) {
3487 stlParentName.Remove(0, motherName.Length());
3488 }
3489 }
3490 }
3491 }
3492 stlParentNameUpdated = true;
3493 if (isBaseSubBranch) {
3494 // -- Remove the base class name suffix from our name.
3495 // Note: The pattern is the name of the base class.
3496 TString pattern(subBranchElement->GetName());
3497 if (pattern.Length() <= dataName.Length()) {
3498 if (!strcmp(dataName.Data() + (dataName.Length() - pattern.Length()), pattern.Data())) {
3499 // The branch name contains the name of the base class in it.
3500 // This name is not reproduced in the sub-branches, so we need to
3501 // remove it.
3502 dataName.Remove(dataName.Length() - pattern.Length());
3503 }
3504 }
3505 // Remove any leading dot.
3506 if (dataName.Length()) {
3507 if (dataName[0] == '.') {
3508 dataName.Remove(0, 1);
3509 }
3510 }
3511 // Note: We intentionally leave any trailing dot
3512 // in our modified name here.
3513 }
3514
3515 // Get our parent branch's name.
3517 if (motherDotAtEnd) {
3518 // -- Remove the top-level branch name from our parent's name.
3519 parentName.Remove(0, motherName.Length());
3520 } else if (motherDot) {
3521 // -- Remove the top-level branch name from our parent's name, folder case.
3522 //
3523 // Note: We are in the case where our mother was created
3524 // by the branch constructor which takes a folder
3525 // as an argument. The mother branch has internal
3526 // dots in its name to represent the folder hierarchy.
3527 // The TTree::Bronch() routine has handled us as a
3528 // special case, we must compensate.
3529 if ((fID > -1) && (mother == mother->GetSubBranch(this)) && (branchElem->IsA() == TStreamerBase::Class())) {
3530 // -- Our parent's name is the mother name, remove it.
3531 // Note: The test is our parent's parent is a top-level branch
3532 // and our parent's streamer is the base class streamer,
3533 // this matches the exact test in TTree::Bronch().
3534 if (parentName.Length() == motherName.Length()) {
3535 parentName.Remove(0, motherName.Length());
3536 }
3537 } else {
3538 // -- Remove the mother name and the dot.
3539 if (parentName.Length() > motherName.Length()) {
3540 parentName.Remove(0, motherName.Length() + 1);
3541 }
3542 }
3543 }
3544 // FIXME: Do we need to use the other tests for a base class here?
3545 if (fType == 1) {
3546 // -- Our parent is a base class sub-branch, remove the base class name suffix from its name.
3547 if (mother != mother->GetSubBranch(this)) {
3548 // -- My parent's parent is not a top-level branch.
3549 // Remove the base class name suffix from the parent name.
3550 // Note: The pattern is the name of the base class.
3551 // coverity[var_deref_model] branchElem is non zero here since fType==1 and thus fID > -1
3552 TString pattern(branchElem->GetName());
3553 if (pattern.Length() <= parentName.Length()) {
3554 if (!strcmp(parentName.Data() + (parentName.Length() - pattern.Length()), pattern.Data())) {
3555 // The branch name contains the name of the base class in it.
3556 // This name is not reproduced in the sub-branches, so we need to
3557 // remove it.
3558 parentName.Remove(parentName.Length() - pattern.Length());
3559 }
3560 }
3561 }
3562 // Note: We intentionally leave any trailing dots
3563 // in the modified parent name here.
3564 }
3565
3566 // Remove the parent branch name part from our name,
3567 // but only if the parent branch is not a top-level branch.
3568 // FIXME: We should not assume parent name does not have length 0.
3569 if (fID > -1) {
3571 }
3572
3573 // Remove any leading dot.
3574 if (dataName.Length()) {
3575 if (dataName[0] == '.') {
3576 dataName.Remove(0, 1);
3577 }
3578 }
3579
3580 // Remove any trailing dot.
3581 if (dataName.Length()) {
3582 if (dataName[dataName.Length()-1] == '.') {
3583 dataName.Remove(dataName.Length() - 1, 1);
3584 }
3585 }
3586
3587 //
3588 // Now that we have our data member name, find our offset
3589 // in our parent class.
3590 //
3591 // Note: Our data member name can have many dots in it
3592 // if branches were elided between our parent branch
3593 // and us by Unroll().
3594 //
3595 // FIXME: This may not work if our member name is ambiguous.
3596 //
3597
3598 Int_t offset = 0;
3599 if (dataName.Length()) {
3600 // -- We have our data member name, do a lookup in the dictionary meta info of our parent class.
3601 // Get our parent class.
3602 TClass* pClass = nullptr;
3603 // First check whether this sub-branch is part of the 'cache' (because the data member it
3604 // represents is no longer in the current class layout.
3605 TStreamerInfo *subInfo = subBranch->GetInfoImp();
3606 //if (subInfo && subBranch->TestBit(kCache)) { // subInfo->GetElements()->At(subBranch->GetID())->TestBit(TStreamerElement::kCache)) {
3608 pClass = static_cast<TStreamerElement*>(subInfo->GetElements()->At(0))->GetClassPointer();
3609 }
3610 // FIXME: Do we need the other base class tests here?
3611 if (!pClass) {
3612 if (fType == 1) {
3613 // -- Parent branch is a base class branch.
3614 // FIXME: Is using branchElem here the right thing?
3615 pClass = branchElem->GetClassPointer();
3616 if (pClass->Property() & kIsAbstract) {
3617 // the class is abstract, let see if the
3618
3619 TBranchElement *parent = static_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
3620 if (parent && parent != this && !parent->GetClass()->IsLoaded() ) {
3621 // Our parent's class is emulated and we represent an abstract class.
3622 // and the target class has not been set explicitly.
3623 TString target = pClass->GetName();
3624 target += "@@emulated";
3625
3627 }
3628 }
3629 } else {
3630 // -- Parent branch is *not* a base class branch.
3631 // FIXME: This sometimes returns a null pointer.
3632 pClass = subBranch->GetParentClass();
3633 }
3634 }
3635 if (!pClass) {
3636 // -- No parent class, fix it.
3637 // FIXME: This is probably wrong!
3638 // Assume parent class is our parent branch's clones class or value class.
3639 if (GetClonesName() && strlen(GetClonesName())) {
3641 if (!pClass) {
3642 Warning("InitializeOffsets", "subBranch: '%s' has no parent class, and cannot get class for clones class: '%s'!", subBranch->GetName(), GetClonesName());
3644 continue;
3645 }
3646 Warning("InitializeOffsets", "subBranch: '%s' has no parent class! Assuming parent class is: '%s'.", subBranch->GetName(), pClass->GetName());
3647 }
3650 Warning("InitializeOffsets", "subBranch: '%s' has no parent class! Assuming parent class is: '%s'.", subBranch->GetName(), pClass ? pClass->GetName() : "unknown class");
3651 }
3652 if (!pClass) {
3653 // -- Still no parent class, assume our parent class is our parent branch's class.
3654 // FIXME: This is probably wrong!
3656 // FIXME: Enable this warning!
3657 //Warning("InitializeOffsets", "subBranch: '%s' has no parent class! Assuming parent class is: '%s'.", subBranch->GetName(), pClass->GetName());
3658 }
3659 }
3660 if (renamed && pClass) {
3661 if (pClass == branchClass) {
3662 pClass = branchElem->GetNewClass();
3663 } else if (fCollProxy && pClass == branchClass->GetCollectionProxy()->GetValueClass()) {
3665 }
3666 }
3667
3668 //------------------------------------------------------------------
3669 // If we have the are the sub-branch of the TBranchSTL, we need
3670 // to remove it's name to get the correct real data offsets
3671 ////////////////////////////////////////////////////////////////////
3672
3673 const bool isToplevelCollection = (this == GetMother() && (fType == 3 || fType == 4));
3674 if( stlParentName.Length() && (dynamic_cast<TBranchSTL*>(fParent) || isToplevelCollection))
3675 {
3676 if( !strncmp( stlParentName.Data(), dataName.Data(), stlParentName.Length()-1 )
3677 && dataName[ stlParentName.Length() ] == '.' )
3678 dataName.Remove( 0, stlParentName.Length()+1 );
3679 }
3680
3681 // Find our offset in our parent class using
3682 // a lookup by name in the dictionary meta info
3683 // for our parent class.
3684
3685 if (alternateElement) {
3686 Ssiz_t dotpos = dataName.Last('.');
3687 Ssiz_t endpos = dataName.Length();
3688 if (dotpos != kNPOS) ++dotpos; else dotpos = 0;
3689 dataName.Replace(dotpos,endpos-dotpos,subBranchElement->GetFullName());
3690 }
3691 TRealData* rd = pClass->GetRealData(dataName);
3692 if (rd && (!rd->TestBit(TRealData::kTransient) || alternateElement)) {
3693 // -- Data member exists in the dictionary meta info, get the offset.
3694 // If we are using an alternateElement, it is the target of a rule
3695 // and might be indeed transient.
3696 offset = rd->GetThisOffset();
3697 } else if (subBranchElement->TestBit(TStreamerElement::kWholeObject)) {
3698 // We are a rule with no specific target, it applies to the whole
3699 // object, let's set the offset to zero
3700 offset = 0;
3701 } else {
3702 // -- No dictionary meta info for this data member, it must no
3703 // longer exist
3704 if (fEntries == 0) {
3705 // ... unless we creating the branch in which case
3706 // we have an internal error.
3707 if (pClass->GetListOfRealData()->GetEntries() == 0) {
3708 // We are probably missing the ShowMember, let's
3709 // just issue an error.
3710 Error("InitializeOffsets",
3711 "Could not find the real data member '%s' when constructing the branch '%s' [Likely missing ShowMember].",
3712 dataName.Data(),GetName());
3713 } else if (subInfo && subInfo->GetClassVersion()!=subInfo->GetClass()->GetClassVersion()) {
3714 // In the case where we are cloning a TTree that was created with an older version of the layout, we may not
3715 // able to find all the members
3716 Info("InitializeOffsets",
3717 "TTree created with an older schema, some data might not be copied in 'slow-cloning' mode; fast-cloning should have the correct result. '%s' is missing when constructing the branch '%s'. ",
3718 dataName.Data(),GetName());
3719 } else {
3720 // Something really bad happen.
3721 Fatal("InitializeOffsets",
3722 "Could not find the real data member '%s' when constructing the branch '%s' [Likely an internal error, please report to the developers].",
3723 dataName.Data(),GetName());
3724 }
3725 }
3727 }
3728 } else {
3729 // -- We have no data member name, ok for a base class, not good otherwise.
3730 if (isBaseSubBranch) {
3731 // I am a direct base class of my parent class, my local offset is enough.
3732 } else {
3733 Warning("InitializeOffsets", "Could not find the data member name for branch '%s' with parent branch '%s', assuming offset is zero!", subBranch->GetName(), GetName());
3734 }
3735 }
3736
3737 //
3738 // Ok, do final calculations for fOffset and fBranchOffset.
3739 //
3740
3741 if (isContDataMember) {
3742 // -- Container data members set fOffset instead of fBranchOffset.
3743 // The fOffset is what should be added to the start of the entry
3744 // in the collection (i.e., its current absolute address) to find
3745 // the beginning of the data member described by the current branch.
3746 //
3747 // Compensate for the i/o routines adding our local offset later.
3748 if (subBranch->fObject == nullptr && localOffset == TStreamerInfo::kMissing) {
3749 subBranch->SetMissing();
3750 // We stil need to set fBranchOffset in the case of a missing
3751 // element so that SetAddress is (as expected) not called
3752 // recursively in this case.
3754 } else {
3755 if (isBaseSubBranch) {
3756 // The value of 'offset' for a base class does not include its
3757 // 'localOffset'.
3758 subBranch->SetOffset(offset);
3759 } else {
3760 // The value of 'offset' for a regular data member does include its
3761 // 'localOffset', we need to remove it explicitly.
3762 subBranch->SetOffset(offset - localOffset);
3763 }
3764 }
3765 } else {
3766 // -- Set fBranchOffset for sub-branch.
3767 Int_t isSplit = 0 != subBranch->GetListOfBranches()->GetEntriesFast();
3768 if (subBranch->fObject == nullptr && localOffset == TStreamerInfo::kMissing) {
3769 // The branch is missing
3771
3772 } else if (isSplit) {
3773 if (isBaseSubBranch) {
3774 // We are split, so we need to add in our local offset
3775 // to get our absolute address for our children.
3777 } else {
3778 // We are split so our offset will never be
3779 // used in an i/o, so we do not have to subtract
3780 // off our local offset like below.
3782 }
3783 } else {
3784 if (isBaseSubBranch) {
3785 // We are not split, so our local offset will be
3786 // added later by the i/o routines.
3788 } else {
3789 // Compensate for the fact that the i/o routines
3790 // are going to add my local offset later.
3792 }
3793 }
3794 }
3795 }
3796 }
3797 else {
3798 if (fID > -1) {
3799 // Branch is *not* a top-level branch.
3800 // Let's check if the target member is still present in memory
3802 fObject = nullptr;
3803 }
3804 }
3805 }
3806 const bool isSplitNode = (fType == 2 || fType == 1 || (fType == 0 && fID == -2)) && !fBranches.IsEmpty();
3808 TBranchElement *parent = dynamic_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
3809 auto index = parent->fBranches.IndexOf(this);
3810 if (index >= 0) {
3812 }
3813 }
3814
3815 fInitOffsets = true;
3816}
3817
3818////////////////////////////////////////////////////////////////////////////////
3819/// Return true if more than one leaf, false otherwise.
3820
3822{
3824 if (nbranches >= 1) {
3825 return true;
3826 }
3827 TList* browsables = const_cast<TBranchElement*>(this)->GetBrowsables();
3828 return browsables && browsables->GetSize();
3829}
3830
3831////////////////////////////////////////////////////////////////////////////////
3832/// Detect a collection written using a zero pointer in old versions of root.
3833/// In versions of ROOT older than 4.00/03, if a collection (TClonesArray
3834/// or STL container) was split but the pointer to the collection was zeroed
3835/// out, nothing was saved. Hence there is no __easy__ way to detect the
3836/// case. In newer versions, a zero is written so that a 'missing' collection
3837/// appears to be an empty collection.
3838
3840{
3841 bool ismissing = false;
3843 if (basket && fTree) {
3846 Long64_t last;
3847 if (fReadBasket == fWriteBasket) {
3848 last = fEntryNumber - 1;
3849 } else {
3850 last = fBasketEntry[fReadBasket+1] - 1;
3851 }
3852 Int_t* entryOffset = basket->GetEntryOffset();
3854 Int_t bufnext;
3855 if (entryOffset) {
3856 bufbegin = entryOffset[entry-first];
3857
3858 if (entry < last) {
3859 bufnext = entryOffset[entry+1-first];
3860 } else {
3861 bufnext = basket->GetLast();
3862 }
3863 if (bufnext == bufbegin) {
3864 ismissing = true;
3865 } else {
3866 // fixed length buffer so this is not the case here.
3867 if (basket->GetNevBufSize() == 0) {
3868 ismissing = true;
3869 }
3870 }
3871 }
3872 }
3873 return ismissing;
3874}
3875
3876////////////////////////////////////////////////////////////////////////////////
3877/// Print branch parameters.
3878
3880{
3881 for(auto &cursor : ids) {
3882 auto id = cursor.fElemID;
3883 if (id >= 0) {
3884 auto el = info->GetElement(id);
3885 if (el)
3886 el->ls();
3887 else {
3888 Error("TBranchElement::Print", "Element for id #%d not found in StreamerInfo for %s",
3889 id, info->GetName());
3890 info->ls();
3891 }
3892 } else if (cursor.fNestedIDs) {
3893 Printf(" Within subobject of type %s offset = %d", cursor.fNestedIDs->fInfo->GetName(), cursor.fNestedIDs->fOffset);
3894 PrintElements(cursor.fNestedIDs->fInfo, cursor.fNestedIDs->fIDs);
3895 }
3896 }
3897}
3898
3900{
3901 constexpr auto length = std::char_traits<char>::length;
3903 if (strncmp(option,"debugAddress",length("debugAddress"))==0) {
3904 if (strlen(option)==length("debugAddress")) {
3905 Printf("%-24s %-16s %2s %4s %-16s %-16s %8s %8s %s %s\n",
3906 "Branch Name", "Streamer Class", "ID", "Type", "Class", "Parent", "pOffset", "fOffset", "fObject", "fOnfileObject");
3907 }
3908 if (strlen(GetName())>24) Printf("%-24s\n%-24s ", GetName(),"");
3909 else Printf("%-24s ", GetName());
3910
3911 TBranchElement *parent = dynamic_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
3912 Int_t ind = parent ? parent->GetListOfBranches()->IndexOf(this) : -1;
3913 TVirtualStreamerInfo *info = const_cast<TBranchElement*>(this)->GetInfoImp();
3914
3915 Printf("%-16s %2d %4d %-16s %-16s %8x %8x %p %p%s\n",
3916 info ? info->GetName() : "StreamerInfo unavailable", GetID(), GetType(),
3918 (fBranchOffset&&parent && ind>=0) ? parent->fBranchOffset[ind] : 0,
3919 GetOffset(), GetObject(), fOnfileObject, TestBit(kOwnOnfileObj) ? " (owned)" : "");
3920 for (Int_t i = 0; i < nbranches; ++i) {
3921 TBranchElement* subbranch = static_cast<TBranchElement*>(fBranches.At(i));
3922 subbranch->Print("debugAddressSub");
3923 }
3924 return;
3925 }
3926 if (strncmp(option,"debugInfo",length("debugInfo"))==0) {
3927 Printf("Branch %s uses:",GetName());
3929 if (fID>= 0) {
3930 // GetInfoImp()->GetElement(fID)->ls();
3931 // for(UInt_t i=0; i< fIDs.size(); ++i) {
3932 // GetInfoImp()->GetElement(fIDs[i])->ls();
3933 // }
3934 if (fType == 3 || fType == 4) {
3935 // Search for the correct version.
3937 }
3938 Printf(" With elements:");
3939 if (fType != 3 && fType != 4)
3940 localInfo->GetElement(fID)->ls();
3942 Printf(" with read actions:");
3944 Printf(" with write actions:");
3946 } else if (!fNewIDs.empty() && localInfo) {
3947 if (fType == 3 || fType == 4) {
3948 // Search for the correct version.
3950 }
3952 Printf(" with read actions:");
3954 Printf(" with write actions:");
3956 }
3957 TString suboption = "debugInfoSub";
3958 suboption += (option+length("debugInfo"));
3959 for (Int_t i = 0; i < nbranches; ++i) {
3960 TBranchElement* subbranch = static_cast<TBranchElement*>(fBranches.At(i));
3961 subbranch->Print(suboption);
3962 }
3963 Printf(" ");
3964 return;
3965 }
3966 if (nbranches) {
3967 if (fID == -2) {
3968 if (strcmp(GetName(),GetTitle()) == 0) {
3969 Printf("*Branch :%-66s *",GetName());
3970 } else {
3971 Printf("*Branch :%-9s : %-54s *",GetName(),GetTitle());
3972 }
3973 Printf("*Entries : %8d : BranchElement (see below) *",Int_t(fEntries));
3974 Printf("*............................................................................*");
3975 }
3976 if (fType >= 2) {
3978 }
3979 for (Int_t i=0;i<nbranches;i++) {
3980 TBranch *branch = static_cast<TBranch*>(fBranches.At(i));
3981 branch->Print(option);
3982 }
3983 } else {
3985 }
3986}
3987
3988////////////////////////////////////////////////////////////////////////////////
3989/// Prints values of leaves.
3990
3992{
3994
3996 Int_t prID = fID;
3997 char *object = fObject;
3998 if (TestBit(kCache)) {
3999 if (info->GetElements()->At(fID)->TestBit(TStreamerElement::kRepeat)) {
4000 prID = fID+1;
4001 } else if (fOnfileObject) {
4002 object = fOnfileObject->GetObjectAt(0);
4003 }
4004 }
4005
4006 if (TestBit(kDecomposedObj)) {
4007 if (!fAddress) {
4008 return;
4009 }
4010 if (fType == 3 || fType == 4) {
4011 // TClonesArray or STL container top-level branch.
4012 printf(" %-15s = %d\n", GetName(), fNdata);
4013 return;
4014 } else if (fType == 31 || fType == 41) {
4015 // TClonesArray or STL container sub-branch.
4016 Int_t n = TMath::Min(10, fNdata);
4019 // TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar is
4020 // printed as a string and could print weird characters.
4021 // So we print an unsigned char instead (not perfect, but better).
4023 }
4024 if (atype > 54) {
4025 // FIXME: More logic required here (like in ReadLeaves)
4026 printf(" %-15s = %d\n", GetName(), fNdata);
4027 return;
4028 }
4029 if (fStreamerType > 20) {
4030 atype -= 20;
4031 TLeafElement* leaf = static_cast<TLeafElement*>(fLeaves.UncheckedAt(0));
4032 n = n * leaf->GetLenStatic();
4033 }
4034 if (info) {
4035 info->PrintValue(GetName(), fAddress, atype, n, lenmax);
4036 }
4037 return;
4038 } else if (fType <= 2) {
4039 // Branch in split mode.
4040 // FIXME: This should probably be < 60 instead.
4041 if ((fStreamerType > 40) && (fStreamerType < 55)) {
4042 Int_t atype = fStreamerType - 20;
4044 Int_t n = (Int_t) counterElement->GetValue(0, 0);
4045 if (info) {
4046 info->PrintValue(GetName(), fAddress, atype, n, lenmax);
4047 }
4048 } else {
4049 if (info) {
4050 info->PrintValue(GetName(), object, prID, -1, lenmax);
4051 }
4052 }
4053 return;
4054 }
4055 } else if (fType == 3) {
4056 printf(" %-15s = %d\n", GetName(), fNdata);
4057 } else if (fType == 31) {
4058 TClonesArray* clones = reinterpret_cast<TClonesArray*>(object);
4059 if (info) {
4060 info->PrintValueClones(GetName(), clones, prID, fOffset, lenmax);
4061 }
4062 } else if (fType == 41) {
4064 if (info) {
4065 info->PrintValueSTL(GetName(), const_cast<TBranchElement*>(this)->GetCollectionProxy(), prID, fOffset, lenmax);
4066 }
4067 } else {
4068 if (info) {
4069 info->PrintValue(GetName(), object, prID, -1, lenmax);
4070 }
4071 }
4072}
4073
4074////////////////////////////////////////////////////////////////////////////////
4075/// Unconfiguration Read Leave function.
4076
4078{
4079 Fatal("ReadLeaves","The ReadLeaves function has not been configured for %s",GetName());
4080}
4081
4082////////////////////////////////////////////////////////////////////////////////
4083/// Read leaves into i/o buffers for this branch.
4084/// For the case where the branch is set in MakeClass mode (decomposed object).
4085
4087{
4089
4090 if (fType == 3 || fType == 4) {
4091 // Top level branch of a TClonesArray.
4092 Int_t *n = reinterpret_cast<Int_t*>(fAddress);
4093 b >> n[0];
4094 if ((n[0] < 0) || (n[0] > fMaximum)) {
4095 if (IsMissingCollection()) {
4096 n[0] = 0;
4097 b.SetBufferOffset(b.Length() - sizeof(n));
4098 } else {
4099 Error("ReadLeaves", "Incorrect size read for the container in %s\nThe size read is %d when the maximum is %d\nThe size is reset to 0 for this entry (%lld)", GetName(), n[0], fMaximum, GetReadEntry());
4100 n[0] = 0;
4101 }
4102 }
4103 fNdata = n[0];
4104 if (fType == 4 && IsAssociativeContainer(fSTLtype)) {
4106 for (Int_t i=0; i<nbranches; i++) {
4107 TBranch *branch = static_cast<TBranch*>(fBranches[i]);
4108 Int_t nb = branch->GetEntry(GetReadEntry(), 1);
4109 if (nb < 0) {
4110 break;
4111 }
4112 }
4113 }
4114 return;
4115 } else if (fType == 31 || fType == 41) { // sub branch of a TClonesArray
4118 // FIXME: This should probably be > 59 instead.
4119 if (atype > 54) return;
4120 if (!fAddress) {
4121 return;
4122 }
4123 Int_t n = fNdata;
4124 if (atype>40) {
4125 atype -= 40;
4126 if (!fBranchCount2) return;
4127 const char *len_where = fBranchCount2->fAddress;
4128 if (!len_where) return;
4130 Int_t length;
4131 Int_t k;
4133 for( k=0; k<n; k++) {
4134 char **where = &((reinterpret_cast<char**>(fAddress))[k]);
4135 delete [] *where;
4136 *where = nullptr;
4137 switch(len_atype) {
4138 case 1: {length = (reinterpret_cast<const Char_t* >(len_where))[k]; break;}
4139 case 2: {length = (reinterpret_cast<const Short_t* >(len_where))[k]; break;}
4140 case 3: {length = (reinterpret_cast<const Int_t* >(len_where))[k]; break;}
4141 case 4: {length = (reinterpret_cast<const Long_t* >(len_where))[k]; break;}
4142 //case 5: {length = (reinterpret_cast<Float_t*>(len_where))[k]; break;}
4143 case 6: {length = (reinterpret_cast<const Int_t* >(len_where))[k]; break;}
4144 //case 8: {length = (reinterpret_cast<Double_t*>(len_where))[k]; break;}
4145 case 11: {length = (reinterpret_cast<const UChar_t* >(len_where))[k]; break;}
4146 case 12: {length = (reinterpret_cast<const UShort_t* >(len_where))[k]; break;}
4147 case 13: {length = (reinterpret_cast<const UInt_t* >(len_where))[k]; break;}
4148 case 14: {length = (reinterpret_cast<const ULong_t* >(len_where))[k]; break;}
4149 case 15: {length = (reinterpret_cast<const ULong64_t*>(len_where))[k]; break;}
4150 case 16: {length = (reinterpret_cast<const Long64_t* >(len_where))[k]; break;}
4151 case 17: {length = (reinterpret_cast<const ULong64_t*>(len_where))[k]; break;}
4152 case 18: {length = (reinterpret_cast<const bool* >(len_where))[k]; break;}
4153 default: continue;
4154 }
4155 b >> isArray;
4156 if (length <= 0) continue;
4157 if (isArray == 0) continue;
4158 switch (atype) {
4159 case 1: {*where=new char[sizeof(Char_t)*length]; b.ReadFastArray(reinterpret_cast<Char_t*>(*where), length); break;}
4160 case 2: {*where=new char[sizeof(Short_t)*length]; b.ReadFastArray(reinterpret_cast<Short_t*>(*where), length); break;}
4161 case 3: {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray(reinterpret_cast<Int_t*>(*where), length); break;}
4162 case 4: {*where=new char[sizeof(Long_t)*length]; b.ReadFastArray(reinterpret_cast<Long_t*>(*where), length); break;}
4163 case 5: {*where=new char[sizeof(Float_t)*length]; b.ReadFastArray(reinterpret_cast<Float_t*>(*where), length); break;}
4164 case 6: {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray(reinterpret_cast<Int_t*>(*where), length); break;}
4165 case 8: {*where=new char[sizeof(Double_t)*length]; b.ReadFastArray(reinterpret_cast<Double_t*>(*where), length); break;}
4166 case 11: {*where=new char[sizeof(UChar_t)*length]; b.ReadFastArray(reinterpret_cast<UChar_t*>(*where), length); break;}
4167 case 12: {*where=new char[sizeof(UShort_t)*length]; b.ReadFastArray(reinterpret_cast<UShort_t*>(*where), length); break;}
4168 case 13: {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray(reinterpret_cast<UInt_t*>(*where), length); break;}
4169 case 14: {*where=new char[sizeof(ULong_t)*length]; b.ReadFastArray(reinterpret_cast<ULong_t*>(*where), length); break;}
4170 case 15: {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray(reinterpret_cast<UInt_t*>(*where), length); break;}
4171 case 16: {*where=new char[sizeof(Long64_t)*length]; b.ReadFastArray(reinterpret_cast<Long64_t*>(*where), length); break;}
4172 case 17: {*where=new char[sizeof(ULong64_t)*length]; b.ReadFastArray(reinterpret_cast<ULong64_t*>(*where), length); break;}
4173 case 18: {*where=new char[sizeof(bool)*length]; b.ReadFastArray(reinterpret_cast<bool*>(*where), length); break;}
4174 }
4175 }
4176 return;
4177 }
4178 if (atype > 20) {
4179 atype -= 20;
4180 TLeafElement *leaf = static_cast<TLeafElement*>(fLeaves.UncheckedAt(0));
4181 n *= leaf->GetLenStatic();
4182 }
4183 switch (atype) {
4184 case 1: {b.ReadFastArray(reinterpret_cast<Char_t*>(fAddress), n); break;}
4185 case 2: {b.ReadFastArray(reinterpret_cast<Short_t*>(fAddress), n); break;}
4186 case 3: {b.ReadFastArray(reinterpret_cast<Int_t*>(fAddress), n); break;}
4187 case 4: {b.ReadFastArray(reinterpret_cast<Long_t*>(fAddress), n); break;}
4188 case 5: {b.ReadFastArray(reinterpret_cast<Float_t*>(fAddress), n); break;}
4189 case 6: {b.ReadFastArray(reinterpret_cast<Int_t*>(fAddress), n); break;}
4190 case 8: {b.ReadFastArray(reinterpret_cast<Double_t*>(fAddress), n); break;}
4191 case 11: {b.ReadFastArray(reinterpret_cast<UChar_t*>(fAddress), n); break;}
4192 case 12: {b.ReadFastArray(reinterpret_cast<UShort_t*>(fAddress), n); break;}
4193 case 13: {b.ReadFastArray(reinterpret_cast<UInt_t*>(fAddress), n); break;}
4194 case 14: {b.ReadFastArray(reinterpret_cast<ULong_t*>(fAddress), n); break;}
4195 case 15: {b.ReadFastArray(reinterpret_cast<UInt_t*>(fAddress), n); break;}
4196 case 16: {b.ReadFastArray(reinterpret_cast<Long64_t*>(fAddress), n); break;}
4197 case 17: {b.ReadFastArray(reinterpret_cast<ULong64_t*>(fAddress), n); break;}
4198 case 18: {b.ReadFastArray(reinterpret_cast<bool*>(fAddress), n); break;}
4199 case 9: {
4201 TStreamerElement* se = static_cast<TStreamerElement*>(si->GetElement(fID));
4202 Double_t *xx = reinterpret_cast<Double_t*>(fAddress);
4203 for (Int_t ii=0;ii<n;ii++) {
4204 b.ReadDouble32(&(xx[ii]),se);
4205 }
4206 break;
4207 }
4208 case 19: {
4210 TStreamerElement* se = static_cast<TStreamerElement*>(si->GetElement(fID));
4211 Float_t *xx = reinterpret_cast<Float_t*>(fAddress);
4212 for (Int_t ii=0;ii<n;ii++) {
4213 b.ReadFloat16(&(xx[ii]),se);
4214 }
4215 break;
4216 }
4217 }
4218 return;
4219 } else if (fType <= 2) { // branch in split mode
4220 // FIXME: This should probably be < 60 instead.
4221 if (fStreamerType > 40 && fStreamerType < 55) {
4222 Int_t atype = fStreamerType - 40;
4223 Int_t n;
4224 if (fBranchCount==nullptr) {
4225 // Missing fBranchCount. let's attempts to recover.
4226
4228 Ssiz_t dot = countname.Last('.');
4229 if (dot>=0) {
4230 countname.Remove(dot+1);
4231 } else {
4232 countname = "";
4233 }
4234 TString counter( GetTitle() );
4235 Ssiz_t loc = counter.Last('[');
4236 if (loc>=0) {
4237 counter.Remove(0,loc+1);
4238 }
4239 loc = counter.Last(']');
4240 if (loc>=0) {
4241 counter.Remove(loc);
4242 }
4243 countname += counter;
4245 }
4246 if (fBranchCount) {
4247 n = (Int_t)fBranchCount->GetValue(0,0);
4248 } else {
4249 Warning("ReadLeaves","Missing fBranchCount for %s. Data will not be read correctly by the MakeClass mode.",GetName());
4250 n = 0;
4251 }
4252 fNdata = n;
4254 b >> isArray;
4255 switch (atype) {
4256 case 1: {b.ReadFastArray(reinterpret_cast<Char_t*>(fAddress), n); break;}
4257 case 2: {b.ReadFastArray(reinterpret_cast<Short_t*>(fAddress), n); break;}
4258 case 3: {b.ReadFastArray(reinterpret_cast<Int_t*>(fAddress), n); break;}
4259 case 4: {b.ReadFastArray(reinterpret_cast<Long_t*>(fAddress), n); break;}
4260 case 5: {b.ReadFastArray(reinterpret_cast<Float_t*>(fAddress), n); break;}
4261 case 6: {b.ReadFastArray(reinterpret_cast<Int_t*>(fAddress), n); break;}
4262 case 8: {b.ReadFastArray(reinterpret_cast<Double_t*>(fAddress), n); break;}
4263 case 11: {b.ReadFastArray(reinterpret_cast<UChar_t*>(fAddress), n); break;}
4264 case 12: {b.ReadFastArray(reinterpret_cast<UShort_t*>(fAddress), n); break;}
4265 case 13: {b.ReadFastArray(reinterpret_cast<UInt_t*>(fAddress), n); break;}
4266 case 14: {b.ReadFastArray(reinterpret_cast<ULong_t*>(fAddress), n); break;}
4267 case 15: {b.ReadFastArray(reinterpret_cast<UInt_t*>(fAddress), n); break;}
4268 case 16: {b.ReadFastArray(reinterpret_cast<Long64_t*>(fAddress), n); break;}
4269 case 17: {b.ReadFastArray(reinterpret_cast<ULong64_t*>(fAddress), n); break;}
4270 case 18: {b.ReadFastArray(reinterpret_cast<bool*>(fAddress), n); break;}
4271 case 9: {
4273 TStreamerElement* se = si->GetElement(fID);
4274 Double_t *xx = reinterpret_cast<Double_t*>(fAddress);
4275 for (Int_t ii=0;ii<n;ii++) {
4276 b.ReadDouble32(&(xx[ii]),se);
4277 }
4278 break;
4279 }
4280 case 19: {
4282 TStreamerElement* se = si->GetElement(fID);
4283 Float_t *xx = reinterpret_cast<Float_t*>(fAddress);
4284 for (Int_t ii=0;ii<n;ii++) {
4285 b.ReadFloat16(&(xx[ii]),se);
4286 }
4287 break;
4288 }
4289 }
4290 } else {
4291 fNdata = 1;
4292 if (fAddress) {
4293 if (fType<0) {
4294 // Non TObject, Non collection classes with a custom streamer.
4295
4296 // if (fObject)
4298 } else {
4300 if (!info) {
4301 return;
4302 }
4303 // Since info is not null, fReadActionSequence is not null either.
4304 b.ApplySequence(*fReadActionSequence, fObject);
4305 }
4307 fNdata = (Int_t) GetValue(0, 0);
4308 }
4309 } else {
4310 fNdata = 0;
4311 }
4312 }
4313 return;
4314 }
4315}
4316
4317////////////////////////////////////////////////////////////////////////////////
4318/// Read leaves into i/o buffers for this branch.
4319/// Case of a collection (fType == 4).
4320
4322{
4324 if (fObject == nullptr)
4325 {
4326 // We have nowhere to copy the data (probably because the data member was
4327 // 'dropped' from the current schema) so let's no copy it in a random place.
4328 return;
4329 }
4330
4331 // STL container master branch (has only the number of elements).
4332 Int_t n;
4333 b >> n;
4334 if ((n < 0) || (n > fMaximum)) {
4335 if (IsMissingCollection()) {
4336 n = 0;
4337 b.SetBufferOffset(b.Length()-sizeof(n));
4338 } else {
4339 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());
4340 n = 0;
4341 }
4342 }
4343 fNdata = n;
4344
4345 R__PushCache onfileObject(b, fOnfileObject, 1);
4346
4347 // Note: Proxy-helper needs to "embrace" the entire
4348 // streaming of this STL container if the container
4349 // is a set/multiset/map/multimap (what we do not
4350 // know here).
4351 // For vector/list/deque Allocate == Resize
4352 // and Commit == noop.
4353 // TODO: Exception safety a la TPushPop
4356 void* alternate = proxy->Allocate(fNdata, true);
4359 } else {
4361 }
4362
4364
4366 for (Int_t i = 0; i < nbranches; ++i) {
4367 TBranch *branch = static_cast<TBranch*>(fBranches[i]);
4368 // To ensure that the sub-branches are read, we need
4369 // reset their entry cursor.
4371 Int_t nb = branch->GetEntry(GetReadEntry(), 1);
4372 if (nb < 0) {
4373 // Give up on i/o failure.
4374 // FIXME: We need an error message here.
4375 break;
4376 }
4377 }
4378 }
4379 //------------------------------------------------------------------------
4380 // We have split this stuff, so we need to create the pointers
4381 /////////////////////////////////////////////////////////////////////////////
4382
4383 if( proxy->HasPointers() && fSplitLevel > TTree::kSplitCollectionOfPointers )
4384 {
4385 TClass *elClass = proxy->GetValueClass();
4386
4387 //--------------------------------------------------------------------
4388 // The allocation is done in this strange way because ReadLeaves
4389 // is being called many times by TTreeFormula!!!
4390 //////////////////////////////////////////////////////////////////////////
4391
4392 Int_t i = 0;
4393 // coverity[returned_null] the fNdata is check enough to prevent the use of null value of At(0)
4394 if( !fNdata || *reinterpret_cast<void**>(proxy->At( 0 )) != nullptr )
4395 i = fNdata;
4396
4397 for( ; i < fNdata; ++i )
4398 {
4399 void **el = reinterpret_cast<void**>(proxy->At( i ));
4400 // coverity[dereference] since this is a member streaming action by definition the collection contains objects and elClass is not null.
4401 *el = elClass->New();
4402 }
4403 }
4404
4405 proxy->Commit(alternate);
4406}
4407
4408////////////////////////////////////////////////////////////////////////////////
4409/// Read leaves into i/o buffers for this branch.
4410/// Case of a data member within a collection (fType == 41).
4411
4413{
4415 if (fObject == nullptr)
4416 {
4417 // We have nowhere to copy the data (probably because the data member was
4418 // 'dropped' from the current schema) so let's no copy it in a random place.
4419 return;
4420 }
4421
4422 // STL container sub-branch (contains the elements).
4424 if (!fNdata) {
4425 return;
4426 }
4427
4428 R__PushCache onfileObject(b, fOnfileObject, fNdata);
4429
4431 if (info == nullptr) return;
4432
4435
4436 // R__ASSERT(0);
4438 b.ApplySequence(*fReadActionSequence,iter->fBegin,iter->fEnd);
4439}
4440
4441////////////////////////////////////////////////////////////////////////////////
4442/// Read leaves into i/o buffers for this branch.
4443/// Case of a data member within a collection (fType == 41).
4444
4446{
4448 if (fObject == nullptr)
4449 {
4450 // We have nowhere to copy the data (probably because the data member was
4451 // 'dropped' from the current schema) so let's no copy it in a random place.
4452 return;
4453 }
4454
4455 // STL container sub-branch (contains the elements).
4457 if (!fNdata) {
4458 return;
4459 }
4460 R__PushCache onfileObject(b, fOnfileObject, fNdata);
4461
4463 if (info == nullptr) return;
4464
4467
4469 b.ApplySequenceVecPtr(*fReadActionSequence,iter->fBegin,iter->fEnd);
4470}
4471
4472////////////////////////////////////////////////////////////////////////////////
4473/// Read leaves into i/o buffers for this branch.
4474/// Case of a data member within a collection (fType == 41).
4475
4477{
4479 if (fObject == nullptr)
4480 {
4481 // We have nowhere to copy the data (probably because the data member was
4482 // 'dropped' from the current schema) so let's no copy it in a random place.
4483 return;
4484 }
4485
4486 // STL container sub-branch (contains the elements).
4488 if (!fNdata) {
4489 return;
4490 }
4491 R__PushCache onfileObject(b, fOnfileObject, fNdata);
4492
4494 if (info == nullptr) return;
4495 // Since info is not null, fReadActionSequence is not null either.
4496
4497 // Still calling PushPop for the legacy entries.
4500
4502 b.ApplySequence(*fReadActionSequence,iter->fBegin,iter->fEnd);
4503}
4504
4505////////////////////////////////////////////////////////////////////////////////
4506/// Read leaves into i/o buffers for this branch.
4507/// Case of a TClonesArray (fType == 3).
4508
4510{
4512 if (fObject == nullptr)
4513 {
4514 // We have nowhere to copy the data (probably because the data member was
4515 // 'dropped' from the current schema) so let's no copy it in a random place.
4516 return;
4517 }
4518
4519 // TClonesArray master branch (has only the number of elements).
4520 Int_t n;
4521 b >> n;
4522 if ((n < 0) || (n > fMaximum)) {
4523 if (IsMissingCollection()) {
4524 n = 0;
4525 b.SetBufferOffset(b.Length()-sizeof(n));
4526 } else {
4527 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());
4528 n = 0;
4529 }
4530 }
4531 fNdata = n;
4532 TClonesArray* clones = reinterpret_cast<TClonesArray*>(fObject);
4533 if (clones->IsZombie()) {
4534 return;
4535 }
4536 // The salient part of Clear is now 'duplicated in ExpandCreateFast (i.e. the
4537 // setting to zero of the unused slots), so we no longer need to call Clear explicitly
4538 // clones->Clear();
4539 clones->ExpandCreateFast(fNdata);
4540}
4541
4542////////////////////////////////////////////////////////////////////////////////
4543/// Read leaves into i/o buffers for this branch.
4544/// Case of a data member within a TClonesArray (fType == 31).
4545
4547{
4548 // No need to validate the address here, if we are a member of a split ClonesArray,
4549 // fID is positive
4550 // ValidateAddress();
4551
4552 if (fObject == nullptr)
4553 {
4554 // We have nowhere to copy the data (probably because the data member was
4555 // 'dropped' from the current schema) so let's no copy it in a random place.
4556 return;
4557 }
4558
4559 // TClonesArray sub-branch (contains the elements).
4561 TClonesArray* clones = reinterpret_cast<TClonesArray*>(fObject);
4562 if (clones->IsZombie()) {
4563 return;
4564 }
4566 if (info==nullptr) return;
4567 // Since info is not null, fReadActionSequence is not null either.
4568
4569 // Note, we could (possibly) save some more, by configuring the action
4570 // based on the value of fOnfileObject rather than pushing in on a stack.
4571 R__PushCache onfileObject(b, fOnfileObject, fNdata);
4572
4573 char **arr = reinterpret_cast<char **>(clones->GetObjectRef());
4574 char **end = arr + fNdata;
4575 b.ApplySequenceVecPtr(*fReadActionSequence,arr,end);
4576}
4577
4578////////////////////////////////////////////////////////////////////////////////
4579/// Read leaves into i/o buffers for this branch.
4580/// For split-class branch, base class branch, data member branch, or top-level branch.
4581/// which do not have a branch count and are not a counter.
4582
4584{
4585 R__ASSERT(fBranchCount==nullptr);
4587
4589 if (fObject == nullptr)
4590 {
4591 // We have nowhere to copy the data (probably because the data member was
4592 // 'dropped' from the current schema) so let's no copy it in a random place.
4593 return;
4594 }
4595
4596 R__PushCache onfileObject(b, fOnfileObject, 1);
4597 // If not a TClonesArray or STL container master branch
4598 // or sub-branch and branch inherits from tobject,
4599 // then register with the buffer so that pointers are
4600 // handled properly.
4601 if (TestBit(kBranchObject)) {
4602 b.MapObject(reinterpret_cast<TObject*>(fObject));
4603 } else if (TestBit(kBranchAny)) {
4604 b.MapObject(fObject, fBranchClass);
4605 }
4606
4607 fNdata = 1;
4609 if (!info) {
4610 return;
4611 }
4612 // Since info is not null, fReadActionSequence is not null either.
4613 b.ApplySequence(*fReadActionSequence, fObject);
4614}
4615
4616////////////////////////////////////////////////////////////////////////////////
4617/// Read leaves into i/o buffers for this branch.
4618/// For split-class branch, base class branch, data member branch, or top-level branch.
4619/// which do have a branch count and are not a counter.
4620
4622{
4624
4626 if (fObject == nullptr)
4627 {
4628 // We have nowhere to copy the data (probably because the data member was
4629 // 'dropped' from the current schema) so let's no copy it in a random place.
4630 return;
4631 }
4632
4633 // If not a TClonesArray or STL container master branch
4634 // or sub-branch and branch inherits from tobject,
4635 // then register with the buffer so that pointers are
4636 // handled properly.
4637 if (TestBit(kBranchObject)) {
4638 b.MapObject(reinterpret_cast<TObject*>(fObject));
4639 } else if (TestBit(kBranchAny)) {
4640 b.MapObject(fObject, fBranchClass);
4641 }
4642
4643 fNdata = (Int_t) fBranchCount->GetValue(0, 0);
4645 if (!info) {
4646 return;
4647 }
4648 R__PushCache onfileObject(b, fOnfileObject,
4649 1); // Here we have a single object that contains a variable size C-style array.
4650 // Since info is not null, fReadActionSequence is not null either.
4651 b.ApplySequence(*fReadActionSequence, fObject);
4652}
4653
4654////////////////////////////////////////////////////////////////////////////////
4655/// Read leaves into i/o buffers for this branch.
4656/// For split-class branch, base class branch, data member branch, or top-level branch.
4657/// which do not have a branch count and are a counter.
4658
4660{
4662 if (fObject == nullptr)
4663 {
4664 // We have nowhere to copy the data (probably because the data member was
4665 // 'dropped' from the current schema) so let's no copy it in a random place.
4666 return;
4667 }
4668
4669 // If not a TClonesArray or STL container master branch
4670 // or sub-branch and branch inherits from tobject,
4671 // then register with the buffer so that pointers are
4672 // handled properly.
4673 if (TestBit(kBranchObject)) {
4674 b.MapObject(reinterpret_cast<TObject*>(fObject));
4675 } else if (TestBit(kBranchAny)) {
4676 b.MapObject(fObject, fBranchClass);
4677 }
4678
4680 if (!info) {
4681 return;
4682 }
4683
4684 R__PushCache onfileObject(b, fOnfileObject, 1);
4685
4686 // Since info is not null, fReadActionSequence is not null either.
4687 b.ApplySequence(*fReadActionSequence, fObject);
4688 fNdata = (Int_t) GetValue(0, 0);
4689}
4690
4691////////////////////////////////////////////////////////////////////////////////
4692/// Read leaves into i/o buffers for this branch.
4693/// Non TObject, Non collection classes with a custom streamer.
4694
4696{
4698 if (fObject == nullptr)
4699 {
4700 // We have nowhere to copy the data (probably because the data member was
4701 // 'dropped' from the current schema) so let's no copy it in a random place.
4702 return;
4703 }
4704
4705 R__PushCache onfileObject(b, fOnfileObject, 1);
4707}
4708
4709////////////////////////////////////////////////////////////////////////////////
4710/// Unconfiguration Fill Leave function.
4711
4713{
4714 Fatal("FillLeaves","The FillLeaves function has not been configured for %s",GetName());
4715}
4716
4717////////////////////////////////////////////////////////////////////////////////
4718/// Delete any object we may have allocated on a previous call to SetAddress.
4719
4721{
4722 if (fObject && TestBit(kDeleteObject)) {
4723 if (IsAutoDelete() && fAddress != reinterpret_cast<char*>(&fObject)) {
4724 *(reinterpret_cast<char**>(fAddress)) = nullptr;
4725 }
4727 if (fType == 3) {
4728 // -- We are a TClonesArray master branch.
4729 TClonesArray::Class()->Destructor(fObject);
4730 fObject = nullptr;
4733 // -- We are a pointer to a TClonesArray.
4734 // We must zero the pointer in the object.
4735 *(reinterpret_cast<char**>(fAddress)) = nullptr;
4736 }
4737 } else if (fType == 4) {
4738 // -- We are an STL container master branch.
4740
4741 if (!proxy) {
4742 Warning("ReleaseObject", "Cannot delete allocated STL container because I do not have a proxy! branch: %s", GetName());
4743 fObject = nullptr;
4744 } else {
4746 if (needDelete && fID >= 0) {
4748 TStreamerElement* se = si->GetElement(fID);
4750 }
4751 if (needDelete) {
4753 proxy->Clear("force");
4754 }
4755 proxy->Destructor(fObject);
4756 fObject = nullptr;
4757 }
4759 // -- We are a pointer to an STL container.
4760 // We must zero the pointer in the object.
4761 *(reinterpret_cast<char**>(fAddress)) = nullptr;
4762 }
4763 } else {
4764 // We are *not* a TClonesArray master branch and we are *not* an STL container master branch.
4766 if (!cl) {
4767 Warning("ReleaseObject", "Cannot delete allocated object because I cannot instantiate a TClass object for its class! branch: '%s' class: '%s'", GetName(), fBranchClass.GetClassName());
4768 fObject = nullptr;
4769 } else {
4771
4772 if (proxy) {
4773 if (fID >= 0) {
4775 TStreamerElement* se = si->GetElement(fID);
4778 proxy->Clear("force");
4779 }
4780 } else if (proxy->GetProperties()&TVirtualCollectionProxy::kNeedDelete) {
4782 proxy->Clear("force");
4783 }
4784
4785 }
4786 cl->Destructor(fObject);
4787 fObject = nullptr;
4788 }
4789 }
4790 }
4791}
4792
4793////////////////////////////////////////////////////////////////////////////////
4794/// Reset a Branch.
4795///
4796/// Existing i/o buffers are deleted.
4797/// Entries, max and min are reset.
4798///
4799
4801{
4803 for (Int_t i = 0; i < nbranches; ++i) {
4804 TBranch* branch = static_cast<TBranch*>(fBranches[i]);
4805 branch->Reset(option);
4806 }
4807 fBranchID = -1;
4809}
4810
4811////////////////////////////////////////////////////////////////////////////////
4812/// Reset a Branch after a Merge operation (drop data but keep customizations)
4813///
4814
4816{
4818 for (Int_t i = 0; i < nbranches; ++i) {
4819 TBranch* branch = static_cast<TBranch*>(fBranches[i]);
4820 branch->ResetAfterMerge(info);
4821 }
4823}
4824
4825////////////////////////////////////////////////////////////////////////////////
4826/// Set branch address to zero and free all allocated memory.
4827
4829{
4830 for (Int_t i = 0; i < fNleaves; ++i) {
4831 TLeaf* leaf = static_cast<TLeaf*>(fLeaves.UncheckedAt(i));
4832 //if (leaf) leaf->SetAddress(0);
4833 leaf->SetAddress(nullptr);
4834 }
4835
4836 // Note: We *must* do the sub-branches first, otherwise
4837 // we may delete the object containing the sub-branches
4838 // before giving them a chance to cleanup.
4840 for (Int_t i = 0; i < nbranches; ++i) {
4841 TBranch* br = static_cast<TBranch*>(fBranches[i]);
4842 if (br) br->ResetAddress();
4843 }
4844
4845 //
4846 // SetAddress may have allocated an object.
4847 //
4848
4849 ReleaseObject();
4850
4852 fAddress = nullptr;
4853 fObject = nullptr;
4854}
4855
4856////////////////////////////////////////////////////////////////////////////////
4857/// Release ownership of any allocated objects.
4858///
4859/// Note: This interface was added so that clone trees could
4860/// be told they do not own the allocated objects.
4861
4863{
4866 for (Int_t i = 0; i < nb; ++i) {
4867 TBranch* br = static_cast<TBranch*>(fBranches[i]);
4868 if (br->InheritsFrom(TBranchElement::Class())) {
4869 static_cast<TBranchElement*>(br)->ResetDeleteObject();
4870 }
4871 }
4872}
4873
4874////////////////////////////////////////////////////////////////////////////////
4875/// \brief Reset offset and StreamerInfo information from this branch.
4876/// \param[in] recurse When true call ResetInitInfo on all subbranches.
4877///
4878
4880{
4881 fInfo = nullptr;
4882 fInit = false;
4883 fInitOffsets = false;
4884 fCurrentClass = nullptr;
4885 delete fReadActionSequence;
4886 fReadActionSequence = nullptr;
4887 delete fFillActionSequence;
4888 fFillActionSequence = nullptr;
4889
4890 if (recurse) {
4892 for (Int_t i = 0; i < nbranches; ++i) {
4893 TBranchElement *sub = static_cast<TBranchElement*>(fBranches[i]);
4894 sub->ResetInitInfo(true);
4895 }
4896 }
4897}
4898
4899////////////////////////////////////////////////////////////////////////////////
4900/// Point this branch at an object.
4901///
4902/// For a sub-branch, addr is a pointer to the branch object.
4903///
4904/// For a top-level branch the meaning of addr is as follows:
4905///
4906/// If addr is zero, then we allocate a branch object
4907/// internally and the branch is the owner of the allocated
4908/// object, not the caller. However the caller may obtain
4909/// a pointer to the branch object with GetObject().
4910/// The pointer is reset to zero (nullptr) when the relevant
4911/// branch object is destroyed.
4912///
4913/// Example:
4914/// ~~~ {.cpp}
4915/// branch->SetAddress(0);
4916/// Event* event = branch->GetObject();
4917/// ... Do some work.
4918/// ~~~
4919/// If addr is not zero, but the pointer addr points at is
4920/// zero, then we allocate a branch object and set the passed
4921/// pointer to point at the allocated object. The caller
4922/// owns the allocated object and is responsible for deleting
4923/// it when it is no longer needed.
4924///
4925/// Example:
4926/// ~~~ {.cpp}
4927/// Event* event = 0;
4928/// branch->SetAddress(&event);
4929/// ... Do some work.
4930/// delete event;
4931/// event = 0;
4932/// ~~~
4933/// If addr is not zero and the pointer addr points at is
4934/// also not zero, then the caller has allocated a branch
4935/// object and is asking us to use it. The caller owns it
4936/// and must delete it when it is no longer needed.
4937///
4938/// Example:
4939/// ~~~ {.cpp}
4940/// Event* event = new Event();
4941/// branch->SetAddress(&event);
4942/// ... Do some work.
4943/// delete event;
4944/// event = 0;
4945/// ~~~
4946/// These rules affect users of TTree::Branch(),
4947/// TTree::SetBranchAddress(), and TChain::SetBranchAddress()
4948/// as well because those routines call this one.
4949///
4950/// An example of a tree with branches with objects allocated
4951/// and owned by us:
4952/// ~~~ {.cpp}
4953/// TFile* f1 = new TFile("myfile_original.root");
4954/// TTree* t1 = f1->Get<TTree>("MyTree");
4955/// TFile* f2 = new TFile("myfile_copy.root", "recreate");
4956/// TTree* t2 = t1->Clone(0);
4957/// for (Int_t i = 0; i < 10; ++i) {
4958/// t1->GetEntry(i);
4959/// t2->Fill();
4960/// }
4961/// t2->Write()
4962/// delete f2;
4963/// f2 = 0;
4964/// delete f1;
4965/// f1 = 0;
4966/// ~~~
4967/// An example of a branch with an object allocated by us,
4968/// but owned by the caller:
4969/// ~~~ {.cpp}
4970/// TFile* f = new TFile("myfile.root", "recreate");
4971/// TTree* t = new TTree("t", "A test tree.")
4972/// Event* event = 0;
4973/// TBranchElement* br = t->Branch("event.", &event);
4974/// for (Int_t i = 0; i < 10; ++i) {
4975/// ... Fill event with meaningful data in some way.
4976/// t->Fill();
4977/// }
4978/// t->Write();
4979/// delete event;
4980/// event = 0;
4981/// delete f;
4982/// f = 0;
4983/// ~~~
4984/// Notice that the only difference between this example
4985/// and the following example is that the event pointer
4986/// is zero when the branch is created.
4987///
4988/// An example of a branch with an object allocated and
4989/// owned by the caller:
4990/// ~~~ {.cpp}
4991/// TFile* f = new TFile("myfile.root", "recreate");
4992/// TTree* t = new TTree("t", "A test tree.")
4993/// Event* event = new Event();
4994/// TBranchElement* br = t->Branch("event.", &event);
4995/// for (Int_t i = 0; i < 10; ++i) {
4996/// ... Fill event with meaningful data in some way.
4997/// t->Fill();
4998/// }
4999/// t->Write();
5000/// delete event;
5001/// event = 0;
5002/// delete f;
5003/// f = 0;
5004/// ~~~
5005/// If AutoDelete is on (see TBranch::SetAutoDelete),
5006/// the top level objet will be deleted and recreate
5007/// each time an entry is read, whether or not the
5008/// TTree owns the object.
5009
5011{
5012 SetAddressImpl(addr, (addr == nullptr), 0);
5013}
5014
5015/// See TBranchElement::SetAddress.
5016/// If implied is true, we do not over-ride existing address for
5017/// sub-branches.
5018/// The `offset` is the offset of the sub-object within its parent,
5019/// it is already included in the addr but is still needed to be added
5020/// the OnfileObject address when/if we need to use that address.
5022{
5023 //
5024 // Don't bother if we are disabled.
5025 //
5026
5027 if (TestBit(kDoNotProcess)) {
5028 return;
5029 }
5030
5031 //
5032 // FIXME: When would this happen?
5033 //
5034
5035 if (fType < -1) {
5036 return;
5037 }
5038
5039 //
5040 // Special case when called from code generated by TTree::MakeClass.
5041 //
5042
5043 if (Longptr_t(addr) == -1) {
5044 // FIXME: Do we have to release an object here?
5045 // ReleaseObject();
5046 fAddress = reinterpret_cast<char*>(-1);
5047 fObject = reinterpret_cast<char*>(-1);
5050 return;
5051 }
5052
5053 //
5054 // Reset last read entry number, we have a new user object now.
5055 //
5056
5057 fReadEntry = -1;
5058
5059 //
5060 // Make sure our branch class is instantiated.
5061 //
5063 if( fTargetClass.GetClassName()[0] ) {
5065 }
5066
5067 //
5068 // Try to build the streamer info.
5069 //
5070
5072
5073 // FIXME: Warn about failure to get the streamer info here?
5074
5075 //
5076 // We may have allocated an object last time we were called.
5077 //
5078
5079 if (fObject && TestBit(kDeleteObject)){
5080 ReleaseObject();
5081 }
5082
5083 //
5084 // Remember the pointer to the pointer to our object.
5085 //
5086
5087 fAddress = reinterpret_cast<char*>(addr);
5088 if (fAddress != reinterpret_cast<char*>(&fObject)) {
5089 fObject = nullptr;
5090 }
5093
5094 //
5095 // Do special stuff if we got called from a MakeClass class.
5096 // Allow sub-branches to have independently set addresses.
5097 //
5098
5099 if (TestBit(kDecomposedObj)) {
5100 if (fID > -1) {
5101 // We are *not* a top-level branch.
5102 if (!info) {
5103 // No streamer info, give up.
5104 // FIXME: We should have an error message here.
5105 fObject = fAddress;
5106 } else {
5107 // Compensate for the fact that the i/o routines
5108 // will add the streamer offset to the address.
5109 fObject = fAddress - info->TStreamerInfo::GetElementOffset(fID);
5110 }
5111 return;
5112 }
5113 }
5114
5115 //
5116 // Check whether the container type is still the same
5117 // to support schema evolution; what is written on the file
5118 // may no longer match the class code which is loaded.
5119 //
5120
5121 if (fType == 3) {
5122 // split TClonesArray, counter/master branch.
5124 if (clm) {
5125 // In case clm derives from an abstract class.
5126 clm->BuildRealData();
5127 clm->GetStreamerInfo();
5128 }
5130 if (newType && (newType != TClonesArray::Class())) {
5131 // The data type of the container has changed.
5132 //
5133 // Let's check if it is a compatible type:
5134 bool matched = false;
5135 if (newType->GetCollectionProxy()) {
5136 TClass *content = newType->GetCollectionProxy()->GetValueClass();
5137 if (clm == content) {
5138 matched = true;
5139 } else {
5140 Warning("SetAddress", "The type of %s was changed from TClonesArray to %s but the content do not match (was %s)!", GetName(), newType->GetName(), GetClonesName());
5141 }
5142 } else {
5143 Warning("SetAddress", "The type of the %s was changed from TClonesArray to %s but we do not have a TVirtualCollectionProxy for that container type!", GetName(), newType->GetName());
5144 }
5145 if (matched) {
5146 // Change from 3/31 to 4/41
5147 SetType(4);
5148 // Set the proxy.
5149 fSTLtype = newType->GetCollectionType();
5150 fCollProxy = newType->GetCollectionProxy()->Generate();
5151
5155
5158 } else if (IsAssociativeContainer(*fCollProxy)) {
5161 } else {
5163 }
5164 } else {
5165 // FIXME: Must maintain fObject here as well.
5166 fAddress = nullptr;
5168 }
5169 }
5170 } else if (fType == 4) {
5171 // split STL container, counter/master branch.
5173 if (newType && (newType != GetCollectionProxy()->GetCollectionClass())) {
5174 // Let's check if it is a compatible type:
5175 TVirtualCollectionProxy* newProxy = newType->GetCollectionProxy();
5177 if (newProxy && (oldProxy->GetValueClass() == newProxy->GetValueClass()) && ((!oldProxy->GetValueClass() && (oldProxy->GetType() == newProxy->GetType())) || (oldProxy->GetValueClass() && (oldProxy->HasPointers() == newProxy->HasPointers())))) {
5178 delete fCollProxy;
5180 fCollProxy = newType->GetCollectionProxy()->Generate();
5182 for (Int_t i = 0; i < nbranches; ++i) {
5184 br->fCollProxy = nullptr;
5185 if (br->fReadActionSequence) {
5186 br->SetReadActionSequence();
5187 }
5188 if (br->fFillActionSequence) {
5189 br->SetFillActionSequence();
5190 }
5191 }
5196 delete fIterators;
5197 delete fPtrIterators;
5200 } else if (IsAssociativeContainer(*fCollProxy)) {
5203 } else {
5205 }
5206 }
5207 else if (newProxy && (oldProxy->HasPointers() == newProxy->HasPointers()) && (oldProxy->GetValueClass()!=nullptr) && (newProxy->GetValueClass()!=nullptr)) {
5208 // Let see if there is a rule to convert the content of the collection into each other.
5209 if (newType->GetSchemaRules()->HasRuleWithSourceClass( oldProxy->GetCollectionClass()->GetName())) {
5210 TClass *oldValueClass = oldProxy->GetValueClass();
5211 delete fCollProxy;
5213 fCollProxy = newType->GetCollectionProxy()->Generate();
5215 for (Int_t i = 0; i < nbranches; ++i) {
5217 br->fCollProxy = nullptr;
5218 if (br->fBranchClass == oldValueClass) {
5219 br->SetTargetClass(fCollProxy->GetValueClass()->GetName());
5220 }
5221 if (br->fReadActionSequence) {
5222 br->SetReadActionSequence();
5223 }
5224 if (br->fFillActionSequence) {
5225 br->SetFillActionSequence();
5226 }
5227 }
5232 delete fIterators;
5233 delete fPtrIterators;
5236 } else if (IsAssociativeContainer(*fCollProxy)) {
5239 } else {
5241 }
5242 } else {
5243 Error("SetAddress","For %s, we can not convert %s into %s\n",
5244 GetName(),oldProxy->GetCollectionClass()->GetName(),newType->GetName());
5245 fAddress = nullptr;
5246 fObject = nullptr;
5248 return;
5249 }
5250 }
5251 else if ((newType == TClonesArray::Class()) && (oldProxy->GetValueClass() && !oldProxy->HasPointers() && oldProxy->GetValueClass()->IsTObject()))
5252 {
5253 // The new collection and the old collection are not compatible,
5254 // we cannot use the new collection to read the data.
5255 // Actually we could check if the new collection is a
5256 // compatible ROOT collection.
5257
5258 // We cannot insure that the TClonesArray is set for the
5259 // proper class (oldProxy->GetValueClass()), so we assume that
5260 // the transformation was done properly by the class designer.
5261
5262 // Change from 4/41 to 3/31
5263 SetType(3);
5264 // Reset the proxy.
5265 fSTLtype = kNone;
5266 switch(fStreamerType) {
5270 break;
5274 break;
5277 break;
5278 }
5279 fClonesClass = oldProxy->GetValueClass();
5281 delete fCollProxy;
5282 fCollProxy = nullptr;
5284 if (clm) {
5285 clm->BuildRealData(); //just in case clm derives from an abstract class
5286 clm->GetStreamerInfo();
5287 }
5291 delete fIterators;
5292 fIterators = nullptr;
5293 delete fPtrIterators;
5294 fPtrIterators =nullptr;
5295 } else {
5296 // FIXME: We must maintain fObject here as well.
5297 Error("SetAddress","For %s can not convert %s into %s\n",GetName(),GetCurrentClass()->GetName(),newType->GetName());
5298 fAddress = nullptr;
5300 return;
5301 }
5302 } else {
5303 if (!fIterators && !fPtrIterators) {
5306 } else if (IsAssociativeContainer(*fCollProxy)) {
5309 } else {
5311 }
5312 }
5313 }
5314 }
5315
5316 //
5317 // Establish the semantics of fObject and fAddress.
5318 //
5319 // Top-level branch:
5320 // fObject is a ptr to the object,
5321 // fAddress is a ptr to a pointer to the object.
5322 //
5323 // Sub-branch:
5324 // fObject is a ptr to the object,
5325 // fAddress is the same as fObject.
5326 //
5327 //
5328 // There are special cases for TClonesArray and STL containers.
5329 // If there is no user-provided object, we allocate one. We must
5330 // also initialize any STL container proxy.
5331 //
5332
5333 if (fType == 3) {
5334 // -- We are a TClonesArray master branch.
5335 if (fAddress) {
5336 // -- We have been given a non-zero address, allocate if necessary.
5338 // -- We are *not* a top-level branch and we are *not* a pointer to a TClonesArray.
5339 // Case of an embedded TClonesArray.
5340 fObject = fAddress;
5341 // Check if it has already been properly built.
5342 TClonesArray* clones = reinterpret_cast<TClonesArray*>(fObject);
5343 if (!clones->GetClass()) {
5345 }
5346 } else {
5347 // -- We are either a top-level branch or we are a subbranch which is a pointer to a TClonesArray.
5348 // Streamer type should be -1 (for a top-level branch) or kObject(p|P) here.
5349 if ((fStreamerType != -1) &&
5352 Error("SetAddress", "TClonesArray with fStreamerType: %d", fStreamerType);
5353 } else if (fStreamerType == -1) {
5354 // -- We are a top-level branch.
5355 TClonesArray** pp = reinterpret_cast<TClonesArray**>(fAddress);
5356 if (!*pp) {
5357 // -- Caller wants us to allocate the clones array, but they will own it.
5358 *pp = new TClonesArray(fClonesClass);
5359 }
5360 fObject = reinterpret_cast<char*>(*pp);
5361 } else {
5362 // -- We are a pointer to a TClonesArray.
5363 // Note: We do this so that the default constructor,
5364 // or the i/o constructor can be lazy.
5365 TClonesArray** pp = reinterpret_cast<TClonesArray**>(fAddress);
5366 if (!*pp) {
5367 // -- Caller wants us to allocate the clones array, but they will own it.
5368 *pp = new TClonesArray(fClonesClass);
5369 }
5370 fObject = reinterpret_cast<char*>(*pp);
5371 }
5372 }
5373 } else {
5374 // -- We have been given a zero address, allocate for top-level only.
5376 // -- We are *not* a top-level branch and we are *not* a pointer to a TClonesArray.
5377 // Case of an embedded TClonesArray.
5378 Error("SetAddress", "Embedded TClonesArray given a zero address for branch '%s'", GetName());
5379 } else {
5380 // -- We are either a top-level branch or we are a subbranch which is a pointer to a TClonesArray.
5381 // Streamer type should be -1 (for a top-level branch) or kObject(p|P) here.
5382 if ((fStreamerType != -1) &&
5385 Error("SetAddress", "TClonesArray with fStreamerType: %d", fStreamerType);
5386 } else if (fStreamerType == -1) {
5387 // -- We are a top-level branch.
5388 // Idea: Consider making a zero address not allocate.
5390 fObject = reinterpret_cast<char*>(new TClonesArray(fClonesClass));
5391 fAddress = reinterpret_cast<char*>(&fObject);
5392 } else {
5393 // -- We are a sub-branch which is a pointer to a TClonesArray.
5394 Error("SetAddress", "Embedded pointer to a TClonesArray given a zero address for branch '%s'", GetName());
5395 }
5396 }
5397 }
5398 } else if (fType == 4) {
5399 // -- We are an STL container master branch.
5400 //
5401 // Initialize fCollProxy.
5403 if (fAddress) {
5404 // -- We have been given a non-zero address, allocate if necessary.
5408 // We are *not* a top-level branch and we are *not* a pointer to an STL container.
5409 // Case of an embedded STL container.
5410 // Note: We test for the kObject and kAny types to support
5411 // the (unwise) choice of inheriting from an STL container.
5412 fObject = fAddress;
5413 } else {
5414 // We are either a top-level branch or subbranch which is a pointer to an STL container.
5415 // Streamer type should be -1 (for a top-level branch) or kSTLp here.
5417 Error("SetAddress",
5418 "Branch %s is a split STL container (fStreamerType is: %d), the address can not be set directly.",
5420 } else if (fStreamerType == -1) {
5421 // -- We are a top-level branch.
5422 void** pp = reinterpret_cast<void**>(fAddress);
5423 if (!*pp) {
5424 // -- Caller wants us to allocate the STL container, but they will own it.
5425 *pp = proxy->New();
5426 if (!(*pp)) {
5427 Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
5428 // FIXME: Should we do this? Lots of other code wants
5429 // fAddress to be zero if no fObject, but is
5430 // that a good thing?
5431 fAddress = nullptr;
5433 }
5434 }
5435 fObject = reinterpret_cast<char*>(*pp);
5436 } else {
5437 // -- We are a pointer to an STL container.
5438 // Note: We do this so that the default constructor,
5439 // or the i/o constructor can be lazy.
5440 void** pp = reinterpret_cast<void**>(fAddress);
5441 if (!*pp) {
5442 // -- Caller wants us to allocate the STL container, but they will own it.
5443 *pp = proxy->New();
5444 if (!(*pp)) {
5445 Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
5446 // FIXME: Should we do this? Lots of other code wants
5447 // fAddress to be zero if no fObject, but is
5448 // that a good thing?
5449 fAddress = nullptr;
5451 }
5452 }
5453 fObject = reinterpret_cast<char*>(*pp);
5454 }
5455 }
5456 } else {
5457 // -- We have been given a zero address, allocate for top-level only.
5461 // We are *not* a top-level branch and we are *not* a pointer to an STL container.
5462 // Case of an embedded STL container.
5463 // Note: We test for the kObject and kAny types to support
5464 // the (unwise) choice of inheriting from an STL container.
5465 Error("SetAddress", "Embedded STL container given a zero address for branch '%s'", GetName());
5466 } else {
5467 // We are either a top-level branch or sub-branch which is a pointer to an STL container.
5468 // Streamer type should be -1 (for a top-level branch) or kSTLp here.
5470 Error("SetAddress",
5471 "Branch %s is a split STL container (fStreamerType is: %d), the address can not be set directly.",
5473 } else if (fStreamerType == -1) {
5474 // -- We are a top-level branch, allocate.
5476 fObject = reinterpret_cast<char*>(proxy->New());
5477 if (fObject) {
5478 fAddress = reinterpret_cast<char*>(&fObject);
5479 } else {
5480 Error("SetAddress", "Failed to allocate STL container for branch '%s'", GetName());
5481 // FIXME: Should we do this? Lots of other code wants
5482 // fAddress to be zero if no fObject, but is
5483 // that a good thing?
5484 fAddress = nullptr;
5486 }
5487 } else {
5488 // -- We are a sub-branch which is a pointer to an STL container.
5489 Error("SetAddress", "Embedded pointer to an STL container given a zero address for branch '%s'", GetName());
5490 }
5491 }
5492 }
5493 } else if (fType == 41) {
5494 // -- We are an STL container sub-branch.
5495 // Initialize fCollProxy.
5497 // We are not at top-level branch.
5498 fObject = fAddress;
5499 } else if (fID < 0) {
5500 // -- We are a top-level branch.
5501 char** pp = reinterpret_cast<char**>(fAddress);
5502 if (pp && *pp) {
5503 // -- Caller provided an i/o buffer for us to use.
5504 fObject = *pp;
5505 } else {
5506 // -- Caller did not provide an i/o buffer for us to use, we must make one for ourselves.
5507 if (clOfBranch) {
5508 if (!pp) {
5509 // -- Caller wants us to own the object.
5511 }
5512 fObject = reinterpret_cast<char*>(clOfBranch->New());
5513 if (pp) {
5514 *pp = fObject;
5515 } else {
5516 fAddress = reinterpret_cast<char*>(&fObject);
5517 }
5518 } else {
5519 Error("SetAddress", "I have no TClass for branch %s, so I cannot allocate an I/O buffer!", GetName());
5520 if (pp) {
5521 fObject = nullptr;
5522 *pp = nullptr;
5523 }
5524 }
5525 }
5526 } else {
5527 // -- We are *not* a top-level branch.
5528 fObject = fAddress;
5529 }
5530
5531 if (!info) {
5532 // FIXME: We need and error message here, no streamer info, so cannot set offsets.
5533 return;
5534 }
5535
5536 // We do this only once because it depends only on
5537 // the type of our object, not on its address.
5538 if (!fInitOffsets) {
5540 }
5541
5542 // We are split, recurse down to our sub-branches.
5543 //
5544 // FIXME: This is a tail recursion, we burn stack.
5546 char *localObject = fObject;
5547 if (fOnfileObject && this != GetMother()) {
5549 }
5550 for (Int_t i = 0; i < nbranches; ++i) {
5551 TBranch *abranch = static_cast<TBranch*>(fBranches.UncheckedAt(i));
5552 // FIXME: This is a tail recursion!
5553 if (fBranchOffset[i] != TStreamerInfo::kMissing && !(implied && abranch->TestBit(kAddressSet))) {
5554 abranch->SetAddressImpl(localObject + fBranchOffset[i], implied, fBranchOffset[i]);
5555 abranch->SetBit(kAddressSet);
5556 if (TestBit(kDecomposedObj) != abranch->TestBit(kDecomposedObj))
5557 abranch->SetMakeClass(TestBit(kDecomposedObj));
5558 } else {
5559 // When the member is missing, just leave the address alone
5560 // (since setting explicitly to 0 would trigger error/warning
5561 // messages).
5562 // abranch->SetAddress(0);
5563 abranch->SetBit(kAddressSet);
5564 }
5565 }
5566}
5567
5568////////////////////////////////////////////////////////////////////////////////
5569/// Reset the basket size for all sub-branches of this branch element.
5570
5572{
5575 for (Int_t i = 0; i < nbranches; ++i) {
5576 TBranch* branch = static_cast<TBranch*>(fBranches[i]);
5577 branch->SetBasketSize(fBasketSize);
5578 }
5579}
5580
5581////////////////////////////////////////////////////////////////////////////////
5582/// Set the branch counter for this branch.
5583
5585{
5587 if (fBranchCount==nullptr) return;
5588
5589 TLeafElement* leafOfCounter = static_cast<TLeafElement*>(brOfCounter->GetListOfLeaves()->At(0));
5590 TLeafElement* leaf = static_cast<TLeafElement*>(GetListOfLeaves()->At(0));
5591 if (leafOfCounter && leaf) {
5592 leaf->SetLeafCount(leafOfCounter);
5593 } else {
5594 if (!leafOfCounter) {
5595 Warning("SetBranchCount", "Counter branch %s for branch %s has no leaves!", brOfCounter->GetName(), GetName());
5596 }
5597 if (!leaf) {
5598 Warning("SetBranchCount", "Branch %s has no leaves!", GetName());
5599 }
5600 }
5601}
5602
5603////////////////////////////////////////////////////////////////////////////////
5604/// Set the branch in a mode where the object are decomposed
5605/// (Also known as MakeClass mode).
5606/// Return whether the setting was possible (it is not possible for
5607/// TBranch and TBranchObject).
5608
5610{
5611 if (decomposeObj)
5612 SetBit(kDecomposedObj); // Same as SetBit(kMakeClass)
5613 else
5615
5617 for (Int_t i = 0; i < nbranches; ++i) {
5618 TBranchElement* branch = static_cast<TBranchElement*>(fBranches[i]);
5619 branch->SetMakeClass(decomposeObj);
5620 }
5623
5624 return true;
5625}
5626
5627////////////////////////////////////////////////////////////////////////////////
5628/// Set object this branch is pointing to.
5629
5631{
5632 if (TestBit(kDoNotProcess)) {
5633 return;
5634 }
5635 fObject = reinterpret_cast<char*>(obj);
5636 SetAddress( &fObject );
5637}
5638
5639////////////////////////////////////////////////////////////////////////////////
5640/// Set offset of the object (to which the data member represented by this
5641/// branch belongs) inside its containing object (if any).
5642
5644{
5645 // We need to make sure that the Read and Write action's configuration
5646 // properly reflect this value.
5647
5649 SetMissing();
5650 return;
5651 }
5652
5653 if (fReadActionSequence) {
5655 }
5656 if (fFillActionSequence) {
5658 }
5659 fOffset = offset;
5660}
5661
5662////////////////////////////////////////////////////////////////////////////////
5663/// Set offset of the object (to which the data member represented by this
5664/// branch belongs) inside its containing object (if any) to mark it as missing.
5665
5667{
5668 // We need to make sure that the Read and Write action's configuration
5669 // properly reflect this value.
5670
5671 if (fReadActionSequence) {
5673 }
5674 if (fFillActionSequence) {
5676 }
5678}
5679
5680
5681////////////////////////////////////////////////////////////////////////////////
5682/// Set the sequence of actions needed to read the data out of the buffer.
5684{
5685 // A 'split' node does not store data itself (it has not associated baskets)
5686 const bool isSplitNode = (fType == 3 || fType == 4 || fType == 2 || fType == 1 || (fType == 0 && fID == -2)) && !fBranches.IsEmpty();
5687
5688 if (!isSplitNode) {
5689 fNewIDs.insert(fNewIDs.begin(),fID); // Include the main element in the sequence.
5690 }
5691
5692 if (actionSequence) delete actionSequence;
5694
5695 actionSequence = original->CreateSubSequence(fNewIDs, fOffset, create);
5696
5697 if (!isSplitNode)
5698 fNewIDs.erase(fNewIDs.begin());
5699
5700 else if (fInitOffsets && fType != 3 && fType != 4) {
5701 // fObject has the address of the sub-object but the streamer action have
5702 // offset relative to the parent.
5703
5704 // Note: We skipped this for the top node of split collection because the
5705 // sequence is about the content, we need to review what happens where an
5706 // action related to the collection itself will land.
5707 TBranchElement *parent = dynamic_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
5708
5709 auto index = parent->fBranches.IndexOf(this);
5710 if (index >= 0) {
5711 actionSequence->AddToOffset( - parent->fBranchOffset[index] );
5712 }
5713 } // else it will be done by InitOffsets
5714}
5715
5716////////////////////////////////////////////////////////////////////////////////
5717/// Set the sequence of actions needed to read the data out of the buffer.
5719{
5720 if (fInfo == nullptr) {
5721 // We are called too soon. We will be called again by InitInfo
5722 return;
5723 }
5724
5726 TClass *originalClass = nullptr;
5728 if (fType == 41) {
5731 } else {
5733 if (GetParentClass() == info->GetClass()) {
5737 } else {
5739 }
5740 } else if (GetCollectionProxy()) {
5741 // Base class and embedded objects.
5743 }
5744 }
5745 } else if (fType == 31) {
5747 } else if (0<=fType && fType<=2) {
5748 // Note: this still requires the ObjectWise sequence to not be optimized!
5750 } else if ( fType == 4 && !fNewIDs.empty()) {
5753 } else if ( fType == 3 && !fNewIDs.empty()) {
5756 }
5757
5758 if (create) {
5760 }
5761}
5762
5763////////////////////////////////////////////////////////////////////////////////
5764/// Set the ReadLeaves pointer to execute the expected operations.
5765
5767{
5768 if (TestBit(kDecomposedObj)) {
5770 } else if (fType == 4) {
5772 } else if (fType == 41) {
5776 } else {
5778 }
5779 } else {
5781 }
5782 } else if (fType == 3) {
5784 } else if (fType == 31) {
5786 } else if (fType < 0) {
5788 } else if (fType == 0 && fID == -1) {
5789 // top-level branch.
5791 if (hasCustomStreamer) {
5792 // We are in the case where the object did *not* have a custom
5793 // Streamer when the TTree was written but now *does* have a custom
5794 // Streamer thus we must use it.
5796 } else {
5798 }
5799 } else if (fType <= 2) {
5800 // split-class branch, base class branch or data member branch.
5801 if (fBranchCount) {
5805 } else {
5807 }
5808 } else {
5809 Fatal("SetReadLeavePtr","Unexpected branch type %d for %s",fType,GetName());
5810 }
5811
5813}
5814
5815////////////////////////////////////////////////////////////////////////////////
5816/// Set the sequence of actions needed to write the data out from the buffer.
5817
5819{
5820 if (fInfo == nullptr) {
5821 // We are called too soon. We will be called again by InitInfo
5822 return;
5823 }
5824
5826 TClass *originalClass = nullptr;
5828 if (fType == 41) {
5831 } else {
5833 if (GetParentClass() == info->GetClass()) {
5834 // if( fTargetClass.GetClassName()[0] && fBranchClass != fTargetClass ) {
5835 // originalClass = fBranchClass;
5836 // create = TStreamerInfoActions::TActionSequence::ConversionWriteMemberWiseActionsViaProxyGetter;
5837 // } else {
5839 // }
5840 } else if (GetCollectionProxy()) {
5841 // Base class and embedded objects.
5843 }
5844 }
5845 } else if (fType == 31) {
5847 } else if (0<=fType && fType<=2) {
5848 // Note: this still requires the ObjectWise sequence to not be optimized!
5850 } else if ( fType == 4 && !fNewIDs.empty()) {
5853 } else if ( fType == 3 && !fNewIDs.empty()) {
5856 }
5857
5858 if (create) {
5860 }
5861}
5862
5863////////////////////////////////////////////////////////////////////////////////
5864/// Set the FillLeaves pointer to execute the expected operations.
5865
5867{
5868 if (TestBit(kDecomposedObj) && ((fType==3)||(fType==31))) {
5870 } else if (fType == 4) {
5872 } else if (fType == 41) {
5876 } else {
5878 }
5881 } else {
5883 }
5884 } else if (fType == 3) {
5886 } else if (fType == 31) {
5888 } else if (fType < 0) {
5890 } else if (fType <=2) {
5891 //split-class branch, base class branch, data member branch, or top-level branch.
5892 if (fBranchCount) {
5896 } else {
5898 }
5899 } else {
5900 Fatal("SetFillLeavePtr","Unexpected branch type %d for %s",fType,GetName());
5901 }
5902
5904}
5905
5906////////////////////////////////////////////////////////////////////////////////
5907/// Set the name of the class of the in-memory object into which the data will
5908/// loaded.
5909
5911{
5912 if (name == nullptr) return;
5913
5914 if (strcmp(fTargetClass.GetClassName(),name) != 0 )
5915 {
5916 // We are changing target class, let's reset the meta information and
5917 // the sub-branches.
5918
5919 ResetInitInfo(/*recurse=*/ false);
5920
5922 for (Int_t i = 0; i < nbranches; ++i) {
5923 TBranchElement *sub = static_cast<TBranchElement*>(fBranches[i]);
5924
5925 if (sub->fTargetClass == fTargetClass ) {
5926 sub->SetTargetClass(name);
5927 } else {
5928 // Since the top level changes, the StreamerInfo (in particular for split collection)
5929 // may still need to change (and the info might be updated else (see for example SetAddress for the
5930 // the case fType 4/41)
5931 sub->ResetInitInfo(true);
5932 }
5933 if (sub->fParentClass == fTargetClass ) {
5935 }
5936 }
5938 }
5939
5940}
5941
5942////////////////////////////////////////////////////////////////////////////////
5943/// If the branch address is not set, we set all addresses starting with
5944/// the top level parent branch. This is required to be done in order for
5945/// GetOffset to be correct and for GetEntry to run.
5946
5948{
5949 // Check to see if the user changed the branch address on us.
5951
5953 // -- Do nothing if already setup or if we are a MakeClass branch.
5954 return;
5955 }
5957}
5958
5959////////////////////////////////////////////////////////////////////////////////
5960/// If the branch address is not set, we set all addresses starting with
5961/// the top level parent branch. This is required to be done in order for
5962/// GetOffset to be correct and for GetEntry to run.
5963
5965{
5966 if (TestBit((long)kDoNotProcess|(long)kAddressSet)) {
5967 // -- Do nothing if we have been told not to.
5968 // Or the data member in this branch is not longer part of the
5969 // parent's layout.
5970 return;
5971 }
5972
5973 //--------------------------------------------------------------------------
5974 // Check if we are splited STL collection of pointers
5975 /////////////////////////////////////////////////////////////////////////////
5976
5978 {
5979 TBranchElement *parent = static_cast<TBranchElement*>(GetMother()->GetSubBranch( this ));
5980
5981 // Make sure the StreamerInfo is loaded and initialized.
5982 GetInfoImp();
5983
5984 if( !parent->GetAddress() )
5985 parent->SetAddress( nullptr );
5986 return;
5987 }
5988
5989 //--------------------------------------------------------------------------
5990 // Any other case
5991 /////////////////////////////////////////////////////////////////////////////
5992
5993 TBranchElement* mother = static_cast<TBranchElement*>(GetMother());
5994 if (!mother) {
5995 return;
5996 }
5997 TClass* cl = TClass::GetClass(mother->GetClassName());
5998
5999 // Make sure the StreamerInfo is loaded and initialized.
6000 GetInfoImp();
6001
6002 if (!cl) {
6003 return;
6004 }
6005
6006 if (!mother->GetAddress()) {
6007 // -- Our top-level branch has no address.
6008 bool motherStatus = mother->TestBit(kDoNotProcess);
6009 mother->ResetBit(kDoNotProcess);
6010 // Note: This will allocate an object.
6011 mother->SetAddress(nullptr);
6013 }
6014}
6015
6016////////////////////////////////////////////////////////////////////////////////
6017/// Stream an object of class TBranchElement.
6018
6020{
6021 if (R__b.IsReading()) {
6022 R__b.ReadClassBuffer(TBranchElement::Class(), this);
6027 // The fAddress and fObject data members are not persistent,
6028 // therefore we do not own anything.
6029 // Also clear the bit possibly set by the schema evolution.
6031 // Fixup a case where the TLeafElement was missing
6032 if ((fType == 0) && (fLeaves.GetEntriesFast() == 0)) {
6033 TLeaf* leaf = new TLeafElement(this, GetTitle(), fID, fStreamerType);
6034 leaf->SetTitle(GetTitle());
6035 fNleaves = 1;
6036 fLeaves.Add(leaf);
6037 fTree->GetListOfLeaves()->Add(leaf);
6038 }
6039
6040 // SetReadLeavesPtr();
6041 }
6042 else {
6044 fDirectory = nullptr; // to avoid recursive calls
6045 {
6046 // Save class version.
6048 // Record only positive 'version number'
6049 if (fClassVersion < 0) {
6051 }
6052 // TODO: Should we clear the kDeleteObject bit before writing?
6053 // If we did we would have to remember the old value and
6054 // put it back, we wouldn't want to forget that we owned
6055 // something just because we got written to disk.
6056 R__b.WriteClassBuffer(TBranchElement::Class(), this);
6057 // Restore class version.
6059 }
6060 //
6061 // Mark all streamer infos used by this branch element
6062 // to be written to our output file.
6063 //
6064 {
6065 R__b.ForceWriteInfo(GetInfoImp(), true);
6066 }
6067 //
6068 // If we are a clones array master branch, or an
6069 // STL container master branch, we must also mark
6070 // the streamer infos used by the value class to
6071 // be written to our output file.
6072 //
6073 if (fType == 3) {
6074 // -- TClonesArray, counter/master branch
6075 //
6076 // We must mark the streamer info for the
6077 // value class to be written to the file.
6078 //
6079 TClass* cl = fClonesClass;
6080 if (cl) {
6081 R__b.ForceWriteInfo(cl->GetStreamerInfo(), true);
6082 }
6083 }
6084 else if (fType == 4) {
6085 // -- STL container, counter/master branch
6086 //
6087 // We must mark the streamer info for the
6088 // value class to be written to the file.
6089 //
6091 if (cp) {
6092 TClass* cl = cp->GetValueClass();
6093 if (cl) {
6094 R__b.ForceWriteInfo(cl->GetStreamerInfo(), true);
6095 }
6096 }
6097 }
6098 // If we are in a separate file, then save
6099 // ourselves as an independent key.
6100 if (!dirsav) {
6101 // Note: No need to restore fDirectory, it was already zero.
6102 return;
6103 }
6104 if (!dirsav->IsWritable()) {
6106 return;
6107 }
6109 if (!pdirectory) {
6111 return;
6112 }
6113 const char* treeFileName = pdirectory->GetFile()->GetName();
6115 const char* motherFileName = treeFileName;
6116 if (mother && (mother != this)) {
6117 motherFileName = mother->GetFileName();
6118 }
6119 if ((fFileName.Length() > 0) && strcmp(motherFileName, fFileName.Data())) {
6120 dirsav->WriteTObject(this);
6121 }
6123 }
6124}
6125
6126
6127////////////////////////////////////////////////////////////////////////////////
6128/// Split class cl into sub-branches of this branch.
6129///
6130/// This version of Unroll was formerly embedded in TTree::BronchExec
6131/// It is moved here so we can make sure to call SetReadActionSequence.
6132
6134{
6135 //
6136 // Do we have a final dot in our name?
6137 //
6138
6139 // Note: The branch constructor which takes a folder as input
6140 // creates top-level branch names with dots in them to
6141 // indicate the folder hierarchy.
6142 const char* dot = strchr(name, '.');
6143 Int_t nch = strlen(name);
6144 bool dotlast = false;
6145 if (nch && (name[nch-1] == '.')) {
6146 dotlast = true;
6147 }
6148
6149 // Loop on all public data members of the class and its base classes and create branches for each one.
6150 TObjArray* blist = this->GetListOfBranches();
6151 TIter next(sinfo->GetElements());
6152 TStreamerElement* element = nullptr;
6153 TString bname;
6154 for (Int_t id = 0; (element = static_cast<TStreamerElement*>(next())); ++id) {
6155 if (element->IsA() == TStreamerArtificial::Class()) {
6156 continue;
6157 }
6158 if (element->TestBit(TStreamerElement::kRepeat)) {
6159 continue;
6160 }
6162 continue;
6163 }
6164 char* pointer = (objptr + element->GetOffset());
6165 // FIXME: This is not good enough, an STL container can be
6166 // a base, and the test will fail.
6167 // See TBranchElement::InitializeOffsets() for the
6168 // correct test.
6169 bool isBase = (element->IsA() == TStreamerBase::Class());
6170 if (isBase) {
6171 TClass* clbase = element->GetClassPointer();
6172 if ((clbase == TObject::Class()) && cl->CanIgnoreTObjectStreamer()) {
6173 // Note: TStreamerInfo::Compile() leaves this element
6174 // out of the optimized info, although it does
6175 // exists in the non-compiled and non-optimized info.
6176 // FIXME: The test that TStreamerInfo::Compile() uses
6177 // is element->GetType() < 0, so that is what
6178 // we should do as well.
6179 continue;
6180 }
6181 if (clbase->GetListOfRealData()->GetSize() == 0) {
6182 // Do not create a branch for empty bases.
6183 continue;
6184 }
6185 }
6186 if (dot) {
6187 if (dotlast) {
6188 bname.Form("%s%s", name, element->GetFullName());
6189 } else {
6190 // FIXME: We are in the case where we have a top-level
6191 // branch name that was created by the branch
6192 // constructor which takes a folder as input.
6193 // The internal dots in the name are in place of
6194 // of the original slashes and represent the
6195 // folder hierarchy.
6196 if (isBase) {
6197 // FIXME: This is very strange, this is the only case where
6198 // we create a branch for a base class that does
6199 // not have the base class name in the branch name.
6200 // FIXME: This is also quite bad since classes with two
6201 // or more base classes end up with sub-branches
6202 // that have the same name.
6203 bname = name;
6204 } else {
6205 bname.Form("%s.%s", name, element->GetFullName());
6206 }
6207 }
6208 } else {
6209 // Note: For a base class element, this results in the branchname
6210 // being the name of the base class.
6211 bname.Form("%s", element->GetFullName());
6212 }
6213
6215 element->GetClass()->GetCollectionProxy() &&
6216 element->GetClass()->GetCollectionProxy()->HasPointers() )
6217 {
6218 TBranchSTL* brSTL = new TBranchSTL(this, bname, element->GetClass()->GetCollectionProxy(), bufsize, splitlevel-1, sinfo, id );
6219 blist->Add(brSTL);
6220 }
6221 else
6222 {
6223 TBranchElement* bre = new TBranchElement(this, bname, sinfo, id, pointer, bufsize, splitlevel - 1);
6224 bre->SetParentClass(cl);
6225 blist->Add(bre);
6226 }
6227 }
6228 // Now that we know that this branch is split, let's redo the actions.
6231}
6232
6233////////////////////////////////////////////////////////////////////////////////
6234/// Split class cl into sub-branches of this branch.
6235///
6236/// Create a sub-branch of this branch for each non-empty,
6237/// non-abstract base class of cl (unless we are a sub-branch
6238/// of a TClonesArray or an STL container, in which case we
6239/// do *not* create a sub-branch), and for each non-split data
6240/// member of cl.
6241///
6242/// Note: We do *not* create sub-branches for base classes of cl
6243/// if we are a sub-branch of a TClonesArray or an STL container.
6244///
6245/// Note: We do *not* create sub-branches for data members which
6246/// have a class type and which we are splitting.
6247///
6248/// Note: The above rules imply that the branch hierarchy increases
6249/// in depth only for base classes of cl (unless we are inside
6250/// of a TClonesArray or STL container, in which case the depth
6251/// does *not* increase, the base class is elided) and for
6252/// TClonesArray or STL container data members (which have one
6253/// additional level of sub-branches). The only other way the
6254/// depth increases is when the top-level branch has a split
6255/// class data member, in that case the constructor will create
6256/// a sub-branch for it. In other words, the interior nodes of
6257/// the branch tree are all either: base class nodes; split
6258/// class nodes which are direct sub-branches of top-level nodes
6259/// (created by TClass::Bronch usually); or TClonesArray or STL
6260/// container master nodes.
6261///
6262/// Note: The exception to the above is for the top-level branches,
6263/// Tree::Bronch creates nodes for everything in that case,
6264/// except for a TObject base class of a class which has the
6265/// can ignore tobject streamer flag set.
6266
6268{
6269 //----------------------------------------------------------------------------
6270 // Handling the case of STL collections of pointers
6271 /////////////////////////////////////////////////////////////////////////////
6272
6275
6277
6278 if ((cl == TObject::Class()) && clParent->CanIgnoreTObjectStreamer()) {
6279 return 0;
6280 }
6281
6283
6284 //
6285 // Do nothing if we couldn't build the streamer info for cl.
6286 //
6287
6288 if (!sinfo) {
6289 return 0;
6290 }
6291
6292 const auto namelen = strlen(name);
6293 bool dotlast = (namelen && (name[namelen-1] == '.'));
6294
6295 Int_t ndata = sinfo->GetNelement();
6296
6297 if ((ndata == 1) && cl->GetCollectionProxy() && !strcmp(sinfo->GetElement(0)->GetName(), "This")) {
6298 // -- Class cl is an STL collection, refuse to split it.
6299 // Question: Why? We certainly could by switching to the value class.
6300 // Partial Answer: Only the branch element constructor can split STL containers.
6301 return 1;
6302 }
6303
6304 for (Int_t elemID = 0; elemID < ndata; ++elemID) {
6305 // -- Loop over all the streamer elements and create sub-branches as needed.
6306 TStreamerElement* elem = sinfo->GetElement(elemID);
6307 if (elem->IsA() == TStreamerArtificial::Class()) {
6308 continue;
6309 }
6310 if (elem->TestBit(TStreamerElement::kRepeat)) {
6311 continue;
6312 }
6313 if (elem->TestBit(TStreamerElement::kCache) && !elem->TestBit(TStreamerElement::kWrite)) {
6314 continue;
6315 }
6316 Int_t offset = elem->GetOffset();
6317 // FIXME: An STL container as a base class gets TStreamerSTL as its class, so this test is not enough.
6318 // See InitializeOffsets() for the proper test.
6319 if (elem->IsA() == TStreamerBase::Class()) {
6320 // -- This is a base class of cl.
6321 TClass* clOfBase = elem->GetClassPointer();
6322 if (!clOfBase || ((clOfBase->Property() & kIsAbstract) && cl->InheritsFrom(TCollection::Class()))) {
6323 // -- Do nothing if we are one of the abstract collection (we know they have no data).
6324 return -1;
6325 }
6326 if ((btype == 31) || (btype == 41)) {
6327 // -- Elide the base-class sub-branches of a split TClonesArray or STL container.
6328 //
6329 // Note: We are eliding the base class here, that is, we never
6330 // create a branch for it, so the branch hierarchy is not
6331 // complete.
6332 // Note: The clParent parameter is the value class of the
6333 // container which we are splitting. It does not
6334 // appear in the branch hierarchy either.
6335 // Note: We can use parent class (clParent) != branch class (elemClass) to detection elision.
6336 Int_t unroll = -1;
6337 if (!elem->CannotSplit() || clOfBase == TObject::Class()) {
6339 }
6340 if (unroll < 0) {
6341 // FIXME: We could not split because we are abstract, should we be doing this?
6342 if (namelen) {
6343 branchname.Form("%s%s%s", name, dotlast ? "" : ".", elem->GetFullName());
6344 } else {
6345 branchname.Form("%s", elem->GetFullName());
6346 }
6347 TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, nullptr, basketsize, 0, btype);
6348 branch->SetParentClass(clParent);
6350 }
6351 } else if (clOfBase->GetListOfRealData()->GetSize()) {
6352 // -- Create a branch for a non-empty base class.
6353 if (namelen) {
6354 branchname.Form("%s%s%s", name, dotlast ? "" : ".", elem->GetFullName());
6355 // Elide the base class name when creating the sub-branches.
6356 // Note: The branch names for sub-branches of a base class branch
6357 // do not represent the full class hierarchy because we do
6358 // this, however it does keep the branch names for the
6359 // inherited data members simple.
6361 // Then reset it to the proper name.
6362 branch->SetName(branchname);
6363 branch->SetTitle(branchname);
6364 branch->SetParentClass(clParent);
6366 } else {
6367 branchname.Form("%s", elem->GetFullName());
6369 branch->SetParentClass(clParent);
6371 }
6372 }
6373 } else {
6374 // -- This is a data member of cl.
6375 if (namelen) {
6376 branchname.Form("%s%s%s", name, dotlast ? "" : ".", elem->GetFullName());
6377 } else {
6378 branchname.Form("%s", elem->GetFullName());
6379 }
6380 if ((splitlevel > 1) && ((elem->IsA() == TStreamerObject::Class()) || (elem->IsA() == TStreamerObjectAny::Class()))) {
6381 // -- We are splitting a non-TClonesArray (may inherit from TClonesArray though), non-STL container object.
6382 //
6383 // Ignore an abstract class.
6384 // FIXME: How could an abstract class get here?
6385 // Partial answer: It is a base class. But this is a data member!
6386 TClass* elemClass = elem->GetClassPointer();
6387 if (!elemClass || elemClass->Property() & kIsAbstract) {
6388 return -1;
6389 }
6390 if (elem->CannotSplit()) {
6391 // We are not splitting.
6392 TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, 0, btype);
6393 branch->SetParentClass(clParent);
6395 } else if (elemClass->InheritsFrom(TClonesArray::Class())) {
6396 // Splitting something derived from TClonesArray.
6398 if (btype == 31 || btype == 41 || elem->CannotSplit()) {
6399 // -- We split the sub-branches of a TClonesArray or an STL container only once.
6400 subSplitlevel = 0;
6401 }
6403 branch->SetParentClass(clParent);
6405 } else {
6406 // Splitting a normal class.
6407 // FIXME: We are eliding the class we are splitting here,
6408 // i.e., we do not create a branch for it, so the
6409 // branch hierarchy does not match the class hierarchy.
6410 // Note: clParent is the class which contains a data member of
6411 // the class type which we are splitting.
6412 // Note: We can use parent class (clParent) != branch class (elemClass) to detection elision.
6414 if (unroll < 0) {
6415 // FIXME: We could not split because we are abstract, should we be doing this?
6416 TBranchElement* branch = new TBranchElement(this, branchname, sinfo, elemID, ptr + offset, basketsize, 0, btype);
6417 branch->SetParentClass(clParent);
6419 }
6420 }
6421 }
6422 else if( elem->GetClassPointer() &&
6423 elem->GetClassPointer()->GetCollectionProxy() &&
6424 elem->GetClassPointer()->GetCollectionProxy()->HasPointers() &&
6425 splitSTLP && fType != 4 )
6426 {
6427
6428 TBranchSTL* branch = new TBranchSTL( this, branchname,
6429 elem->GetClassPointer()->GetCollectionProxy(),
6431 branch->SetAddress( ptr+offset );
6432 fBranches.Add( branch );
6433 }
6434 else if ((elem->IsA() == TStreamerSTL::Class()) && !elem->IsaPointer()) {
6435 // -- We have an STL container.
6436 // Question: What if splitlevel == 0 here?
6437 // Answer: then we should not be here.
6439 if ((btype == 31) || (btype == 41) || elem->CannotSplit()) {
6440 // -- We split the sub-branches of a TClonesArray or an STL container only once.
6441 subSplitlevel = 0;
6442 }
6444 branch->SetParentClass(clParent);
6446 } else if (((btype != 31) && (btype != 41)) && ptr && ((elem->GetClassPointer() == TClonesArray::Class()) || ((elem->IsA() == TStreamerSTL::Class()) && !elem->CannotSplit()))) {
6447 // -- We have a TClonesArray.
6448 // FIXME: We could get a ptr to a TClonesArray here by mistake.
6449 // Question: What if splitlevel == 0 here?
6450 // Answer: then we should not be here.
6451 // Note: ptr may be null in case of a TClonesArray inside another
6452 // TClonesArray or STL container, see the else clause.
6454 branch->SetParentClass(clParent);
6456 } else {
6457 // -- We are not going to split this element any farther.
6459 branch->SetType(btype);
6460 branch->SetParentClass(clParent);
6462 }
6463 }
6464 }
6465
6466 if (!fBranches.IsEmpty()) {
6467 // Refresh this branch's action now that we know whether it is split or not.
6470 }
6471 return 1;
6472}
6473
6474////////////////////////////////////////////////////////////////////////////////
6475/// Refresh the value of fDirectory (i.e. where this branch writes/reads its buffers)
6476/// with the current value of fTree->GetCurrentFile unless this branch has been
6477/// redirected to a different file. Also update the sub-branches.
6478
6480{
6481 // The BranchCount and BranchCount2 are part of higher level branches' list of
6482 // branches.
6483 // if (fBranchCount) fBranchCount->UpdateFile();
6484 // if (fBranchCount2) fBranchCount2->UpdateFile();
6486}
static void unroll(CPyCppyy_PyArgs_t packed_args, CPyCppyy_PyArgs_t unrolled, Py_ssize_t nArgs)
fBuffer
const Handle_t kNone
Definition GuiTypes.h:88
#define R__unlikely(expr)
Definition RConfig.hxx:599
#define b(i)
Definition RSha256.hxx:100
#define e(i)
Definition RSha256.hxx:103
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
unsigned short UShort_t
Definition RtypesCore.h:40
int Int_t
Definition RtypesCore.h:45
float Size_t
Definition RtypesCore.h:89
long Longptr_t
Definition RtypesCore.h:75
unsigned char UChar_t
Definition RtypesCore.h:38
int Ssiz_t
Definition RtypesCore.h:67
char Char_t
Definition RtypesCore.h:37
unsigned long ULong_t
Definition RtypesCore.h:55
long Long_t
Definition RtypesCore.h:54
unsigned int UInt_t
Definition RtypesCore.h:46
float Float_t
Definition RtypesCore.h:57
short Short_t
Definition RtypesCore.h:39
double Double_t
Definition RtypesCore.h:59
long double LongDouble_t
Definition RtypesCore.h:61
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:117
long long Long64_t
Definition RtypesCore.h:69
unsigned long long ULong64_t
Definition RtypesCore.h:70
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:374
static void PrintElements(const TStreamerInfo *info, const TStreamerInfoActions::TIDs &ids)
Print branch parameters.
static void R__CleanName(std::string &name)
Remove trailing dimensions and make sure there is a trailing dot.
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
EDataType
Definition TDataType.h:28
@ kOther_t
Definition TDataType.h:32
@ kIsAbstract
Definition TDictionary.h:71
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t cursor
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
Int_t gDebug
Definition TROOT.cxx:622
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:414
static TClass * Class()
Definition Class.C:29
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
#define R__LOCKGUARD_IMT(mutex)
#define R__LOCKGUARD(mutex)
#define gPad
A helper class for managing IMT work during TTree:Fill operations.
const_iterator begin() const
const_iterator end() const
TIOFeatures provides the end-user with the ability to change the IO behavior of data written via a TT...
Manages buffers for branches of a Tree.
Definition TBasket.h:34
A Branch for the case of an object.
void ReadLeavesClonesMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
void SetActionSequence(TClass *originalClass, TStreamerInfo *localInfo, TStreamerInfoActions::TActionSequence::SequenceGetter_t create, TStreamerInfoActions::TActionSequence *&actionSequence)
Set the sequence of actions needed to read the data out of the buffer.
char * fObject
! Pointer to object at *fAddress
TStreamerInfo * fInfo
! Pointer to StreamerInfo
Int_t fSTLtype
! STL container type
void ReadLeavesCustomStreamer(TBuffer &b)
Read leaves into i/o buffers for this branch.
void Reset(Option_t *option="") override
Reset a Branch.
void SetParentClass(TClass *clparent)
TBranchElement * fBranchCount2
pointer to secondary branchcount branch
static TClass * Class()
Int_t fNdata
! Number of data in this branch
~TBranchElement() override
Destructor.
void SetOffset(Int_t offset) override
Set offset of the object (to which the data member represented by this branch belongs) inside its con...
void FillLeavesCollectionMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
TString fClassName
Class name of referenced object.
TStreamerInfoActions::TActionSequence * fFillActionSequence
! Set of actions to be executed to write the data to the basket.
void Print(Option_t *option="") const override
Print TBranch parameters.
void SetAddressImpl(void *addr, bool implied, Int_t offset) override
See TBranchElement::SetAddress.
Int_t GetID() const
const char * GetClassName() const override
Return the name of the user class whose content is stored in this branch, if any.
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
void ReadLeavesCollection(TBuffer &b)
Read leaves into i/o buffers for this branch.
void SetupAddresses() override
If the branch address is not set, we set all addresses starting with the top level parent branch.
void ResetAddress() override
Set branch address to zero and free all allocated memory.
virtual void SetType(Int_t btype)
void FillLeavesMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
void SetBranchCount(TBranchElement *bre)
Set the branch counter for this branch.
static void SwitchContainer(TObjArray *)
Modify the container type of the branches.
void SetReadActionSequence()
Set the sequence of actions needed to read the data out of the buffer.
bool IsMissingCollection() const
Detect a collection written using a zero pointer in old versions of root.
Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *) override
Loop on all leaves of this branch to fill the basket buffer.
TVirtualCollectionProxy * GetCollectionProxy()
Return the collection proxy describing the branch content, if any.
@ kOwnOnfileObj
We are the owner of fOnfileObject.
@ kAddressSet
The addressing set have been called for this branch.
@ kDecomposedObj
More explicit alias for kMakeClass.
@ kDeleteObject
We are the owner of fObject.
@ kCache
Need to pushd/pop fOnfileObject.
void SetupAddressesImpl()
If the branch address is not set, we set all addresses starting with the top level parent branch.
void SetBasketSize(Int_t bufsize) override
Reset the basket size for all sub-branches of this branch element.
Int_t GetEntry(Long64_t entry=0, Int_t getall=0) override
Read all branches of a BranchElement and return total number of bytes.
TClassRef fParentClass
! Reference to class definition in fParentName
Double_t GetValue(Int_t i, Int_t len, bool subarr=false) const
bool fInInitInfo
! True during the 2nd part of InitInfo (cut recursion).
void BuildTitle(const char *name)
Set branch and leaf name and title in the case of a container sub-branch.
virtual Int_t GetMaximum() const
Return maximum count value of the branchcount if any.
TString fParentName
Name of parent class.
void ReadLeavesCollectionSplitPtrMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
TClassRef fBranchClass
! Reference to class definition in fClassName
TStreamerInfoActions::TIDs fNewIDs
! Nested List of the serial number of all the StreamerInfo to be used.
Int_t GetStreamerType() const
TClass * GetCurrentClass()
Return a pointer to the current type of the data member corresponding to branch element.
UInt_t fCheckSum
CheckSum of class.
void ResetAfterMerge(TFileMergeInfo *) override
Reset a Branch after a Merge operation (drop data but keep customizations)
TStreamerInfoActions::TActionSequence * fReadActionSequence
! Set of actions to be executed to extract the data from the basket.
void FillLeavesClones(TBuffer &b)
Write leaves into i/o buffers for this branch.
void ReadLeavesMemberBranchCount(TBuffer &b)
Read leaves into i/o buffers for this branch.
void SetReadLeavesPtr()
Set the ReadLeaves pointer to execute the expected operations.
Int_t Unroll(const char *name, TClass *cltop, TClass *cl, char *ptr, Int_t basketsize, Int_t splitlevel, Int_t btype)
Split class cl into sub-branches of this branch.
void FillLeavesMakeClass(TBuffer &b)
Write leaves into i/o buffers for this branch.
void FillLeavesCollectionSplitVectorPtrMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
void FillLeavesCollection(TBuffer &b)
Write leaves into i/o buffers for this branch.
Int_t fID
element serial number in fInfo
char * GetAddress() const override
Get the branch address.
void FillLeavesMemberCounter(TBuffer &b)
Write leaves into i/o buffers for this branch.
void FillLeavesCollectionSplitPtrMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
void SetAddress(void *addobj) override
Point this branch at an object.
TStreamerInfo * GetInfoImp() const
Get streamer info for the branch class.
virtual void SetTargetClass(const char *name)
Set the name of the class of the in-memory object into which the data will loaded.
virtual void ResetDeleteObject()
Release ownership of any allocated objects.
virtual const char * GetParentName() const
void ValidateAddress() const
TVirtualCollectionIterators * fWriteIterators
! holds the read (non-staging) iterators when the branch is of fType==4 and associative containers.
void PrintValue(Int_t i) const
Prints values of leaves.
TVirtualArray * fOnfileObject
! Place holder for the onfile representation of data members.
virtual const char * GetTypeName() const
Return type name of element in the branch.
void FillLeavesAssociativeCollectionMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
void Init(TTree *tree, TBranch *parent, const char *name, TStreamerInfo *sinfo, Int_t id, char *pointer, Int_t basketsize=32000, Int_t splitlevel=0, Int_t btype=0)
Init when the branch object is not a TClonesArray nor an STL container.
T GetTypedValue(Int_t i, Int_t len, bool subarr=false) const
TClassRef fClonesClass
! Reference to class definition in fClonesName
virtual void * GetValuePointer() const
Returns pointer to first data element of this branch.
void ReadLeavesImpl(TBuffer &b)
Unconfiguration Read Leave function.
bool fInitOffsets
! Initialization flag to not endlessly recalculate offsets
void SetupInfo()
Set the value of fInfo.
void FillLeavesImpl(TBuffer &b)
Unconfiguration Fill Leave function.
void FillLeavesClonesMember(TBuffer &b)
Write leaves into i/o buffers for this branch.
TClassRef fCurrentClass
! Reference to current (transient) class definition
char * GetObject() const
Return a pointer to our object.
void UpdateFile() override
Refresh the value of fDirectory (i.e.
TStreamerInfo * FindOnfileInfo(TClass *valueClass, const TObjArray &branches) const
bool SetMakeClass(bool decomposeObj=true) override
Set the branch in a mode where the object are decomposed (Also known as MakeClass mode).
void ReadLeavesClones(TBuffer &b)
Read leaves into i/o buffers for this branch.
Int_t * fBranchOffset
! Sub-Branch offsets with respect to current transient class
Int_t fType
Branch type.
virtual void ResetInitInfo(bool recurse)
Reset offset and StreamerInfo information from this branch.
friend class TLeafElement
TString GetFullName() const override
Return the 'full' name of the branch.
void ReadLeavesMakeClass(TBuffer &b)
Read leaves into i/o buffers for this branch.
TBranchElement()
Default and I/O constructor.
void FillLeavesCustomStreamer(TBuffer &b)
Write leaves into i/o buffers for this branch.
virtual const char * GetClonesName() const
virtual TClass * GetClass() const
Int_t fMaximum
Maximum entries for a TClonesArray or variable array.
void ReadLeavesMemberCounter(TBuffer &b)
Read leaves into i/o buffers for this branch.
Int_t fBranchID
! ID number assigned by a TRefTable.
TLeaf * FindLeaf(const char *name) override
Find the leaf corresponding to the name 'searchname'.
TVirtualCollectionIterators * fIterators
! holds the iterators when the branch is of fType==4.
void ReleaseObject()
Delete any object we may have allocated on a previous call to SetAddress.
TClassRef fTargetClass
! Reference to the target in-memory class
void Browse(TBrowser *b) override
Browse the branch content.
void FillLeavesMemberBranchCount(TBuffer &b)
Write leaves into i/o buffers for this branch.
bool IsFolder() const override
Return true if more than one leaf, false otherwise.
virtual void SetMissing()
Set offset of the object (to which the data member represented by this branch belongs) inside its con...
TString fClonesName
Name of class in TClonesArray (if any)
TBranchElement * fBranchCount
pointer to primary branchcount branch
Int_t GetType() const
void ReadLeavesMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
Version_t fClassVersion
Version number of class.
TVirtualCollectionPtrIterators * fPtrIterators
! holds the iterators when the branch is of fType==4 and it is a split collection of pointers.
TBranch * FindBranch(const char *name) override
Find the immediate sub-branch with passed name.
void Streamer(TBuffer &) override
Stream an object of class TBranchElement.
virtual void InitInfo()
Init the streamer info for the branch class, try to compensate for class code unload/reload and schem...
virtual void InitializeOffsets()
Initialize the base class subobjects offsets of our sub-branches and set fOffset if we are a containe...
const char * GetIconName() const override
Return icon name depending on type of branch element.
TClass * GetParentClass()
Return a pointer to the parent class of the branch element.
Int_t GetNdata() const
Int_t GetExpectedType(TClass *&clptr, EDataType &type) override
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
bool fInit
! Initialization flag for branch assignment
TVirtualCollectionProxy * fCollProxy
! collection interface (if any)
void SetFillActionSequence()
Set the sequence of actions needed to write the data out from the buffer.
void SetObject(void *objadd) override
Set object this branch is pointing to.
Int_t fStreamerType
branch streamer type
void ReadLeavesCollectionSplitVectorPtrMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
bool GetMakeClass() const override
Return whether this branch is in a mode where the object are decomposed or not (Also known as MakeCla...
void SetFillLeavesPtr()
Set the FillLeaves pointer to execute the expected operations.
void ReadLeavesCollectionMember(TBuffer &b)
Read leaves into i/o buffers for this branch.
A branch containing and managing a TRefTable for TRef autoloading.
Definition TBranchRef.h:34
A Branch handling STL collection of pointers (vectors, lists, queues, sets and multisets) while stori...
Definition TBranchSTL.h:22
A TTree is a list of TBranches.
Definition TBranch.h:93
TString fFileName
Name of file where buffers are stored ("" if in same file as Tree header)
Definition TBranch.h:149
Int_t fEntryOffsetLen
Initial Length of fEntryOffset table in the basket buffers.
Definition TBranch.h:119
Int_t fMaxBaskets
Maximum number of Baskets so far.
Definition TBranch.h:125
TTree * GetTree() const
Definition TBranch.h:252
FillLeaves_t fFillLeaves
! Pointer to the FillLeaves implementation to use.
Definition TBranch.h:163
virtual TString GetFullName() const
Return the 'full' name of the branch.
Definition TBranch.cxx:2031
void(TBranch::* ReadLeaves_t)(TBuffer &b)
Definition TBranch.h:160
@ kBranchAny
Branch is an object*.
Definition TBranch.h:108
@ kBranchObject
Branch is a TObject*.
Definition TBranch.h:107
@ kDoNotProcess
Active bit for branches.
Definition TBranch.h:105
TObjArray fLeaves
-> List of leaves of this branch
Definition TBranch.h:139
char * fAddress
! Address of 1st leaf (variable or object)
Definition TBranch.h:147
TObjArray * GetListOfBranches()
Definition TBranch.h:246
virtual TList * GetBrowsables()
Returns (and, if 0, creates) browsable objects for this branch See TVirtualBranchBrowsable::FillListO...
Definition TBranch.cxx:1312
Int_t fOffset
Offset of this branch.
Definition TBranch.h:124
Long64_t * fBasketEntry
[fMaxBaskets] Table of first entry in each basket
Definition TBranch.h:142
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition TBranch.cxx:1706
TIOFeatures GetIOFeatures() const
Returns the IO settings currently in use for this branch.
Definition TBranch.cxx:2255
Long64_t fReadEntry
! Current entry number when reading
Definition TBranch.h:130
void Print(Option_t *option="") const override
Print TBranch parameters.
Definition TBranch.cxx:2341
TBranch * GetSubBranch(const TBranch *br) const
Find the parent branch of child.
Definition TBranch.cxx:2164
ReadLeaves_t fReadLeaves
! Pointer to the ReadLeaves implementation to use.
Definition TBranch.h:161
void(TBranch::* FillLeaves_t)(TBuffer &b)
Definition TBranch.h:162
virtual void SetAutoDelete(bool autodel=true)
Set the automatic delete bit.
Definition TBranch.cxx:2729
Int_t GetOffset() const
Definition TBranch.h:235
virtual TLeaf * FindLeaf(const char *name)
Find the leaf corresponding to the name 'searchname'.
Definition TBranch.cxx:1081
Long64_t GetReadEntry() const
Definition TBranch.h:237
Long64_t GetEntries() const
Definition TBranch.h:251
Int_t fNleaves
! Number of leaves
Definition TBranch.h:128
Int_t fSplitLevel
Branch split level.
Definition TBranch.h:127
virtual void UpdateFile()
Refresh the value of fDirectory (i.e.
Definition TBranch.cxx:3317
Int_t * fBasketBytes
[fMaxBaskets] Length of baskets on file
Definition TBranch.h:141
bool IsAutoDelete() const
Return true if an existing object in a TBranchObject must be deleted.
Definition TBranch.cxx:2263
TObjArray fBranches
-> List of Branches of this branch
Definition TBranch.h:138
virtual void ResetAfterMerge(TFileMergeInfo *)
Reset a Branch.
Definition TBranch.cxx:2598
virtual TBranch * FindBranch(const char *name)
Find the immediate sub-branch with passed name.
Definition TBranch.cxx:1035
TDirectory * fDirectory
! Pointer to directory where this branch buffers are stored
Definition TBranch.h:148
TObjArray fBaskets
-> List of baskets of this branch
Definition TBranch.h:140
void SetIOFeatures(TIOFeatures &features)
Definition TBranch.h:283
TBranch * fMother
! Pointer to top-level parent branch in the tree.
Definition TBranch.h:145
TBranch * fParent
! Pointer to parent branch.
Definition TBranch.h:146
Int_t fWriteBasket
Last basket number written.
Definition TBranch.h:120
Long64_t * fBasketSeek
[fMaxBaskets] Addresses of baskets on file
Definition TBranch.h:143
TObjArray * GetListOfLeaves()
Definition TBranch.h:247
Int_t fReadBasket
! Current basket number when reading
Definition TBranch.h:129
Int_t fBasketSize
Initial Size of Basket Buffer.
Definition TBranch.h:118
virtual void Reset(Option_t *option="")
Reset a Branch.
Definition TBranch.cxx:2557
virtual void SetBasketSize(Int_t bufsize)
Set the basket size The function makes sure that the basket size is greater than fEntryOffsetlen.
Definition TBranch.cxx:2742
Long64_t fEntryNumber
Current entry number (last one filled in this branch)
Definition TBranch.h:121
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition TBranch.cxx:2127
Int_t fCompress
Compression level and algorithm.
Definition TBranch.h:117
virtual Int_t FillImpl(ROOT::Internal::TBranchIMTHelper *)
Loop on all leaves of this branch to fill Basket buffer.
Definition TBranch.cxx:856
Long64_t fEntries
Number of entries.
Definition TBranch.h:134
TTree * fTree
! Pointer to Tree header
Definition TBranch.h:144
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
Buffer base class used for serializing objects.
Definition TBuffer.h:43
@ kRead
Definition TBuffer.h:73
TClassRef is used to implement a permanent reference to a TClass object.
Definition TClassRef.h:29
void SetName(const char *new_name)
Definition TClassRef.h:62
TClass * GetClass() const
Definition TClassRef.h:67
const char * GetClassName()
Definition TClassRef.h:66
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
void Streamer(void *obj, TBuffer &b, const TClass *onfile_class=nullptr) const
Definition TClass.h:616
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition TClass.cxx:3571
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition TClass.cxx:2425
TVirtualStreamerInfo * GetStreamerInfoAbstractEmulated(Int_t version=0) const
For the case where the requestor class is emulated and this class is abstract, returns a pointer to t...
Definition TClass.cxx:4837
void CopyCollectionProxy(const TVirtualCollectionProxy &)
Replaces the collection proxy for this class.
Definition TClass.cxx:2576
Bool_t HasCustomStreamerMember() const
The class has a Streamer method and it is implemented by the user or an older (not StreamerInfo based...
Definition TClass.h:515
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5540
TClassStreamer * GetStreamer() const
Return the Streamer Class allowing streaming (if any).
Definition TClass.cxx:3020
Bool_t CanIgnoreTObjectStreamer()
Definition TClass.h:399
const TObjArray * GetStreamerInfos() const
Definition TClass.h:499
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:6055
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition TClass.cxx:6081
Bool_t IsForeign() const
Return kTRUE is the class is Foreign (the class does not have a Streamer method).
Definition TClass.cxx:6090
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition TClass.cxx:4727
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:5002
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:3003
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition TClass.cxx:6229
TVirtualStreamerInfo * FindStreamerInfo(TObjArray *arr, UInt_t checksum) const
Find the TVirtualStreamerInfo in the StreamerInfos corresponding to checksum.
Definition TClass.cxx:7222
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:3074
An array of clone (identical) objects.
static TClass * Class()
static TClass * Class()
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
const char * GetTypeName() const
Get the decayed type name of this data member, removing const and volatile qualifiers,...
Basic data type descriptor (datatype information is obtained from CINT).
Definition TDataType.h:44
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TFile * GetFile() const
Definition TDirectory.h:220
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
A TLeaf for the general case when using the branches created via a TStreamerInfo (i....
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
A doubly linked list.
Definition TList.h:38
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:174
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
TString fName
Definition TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition TNamed.cxx:150
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
Int_t IndexOf(const TObject *obj) const override
Int_t GetEntries() const override
Return the number of objects in array (i.e.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
Bool_t IsEmpty() const override
Definition TObjArray.h:65
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Mother of all ROOT objects.
Definition TObject.h:41
friend class TClonesArray
Definition TObject.h:246
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:205
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
static TClass * Class()
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:864
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1099
virtual TClass * IsA() const
Definition TObject.h:249
void ResetBit(UInt_t f)
Definition TObject.h:204
The TRealData class manages the effective list of all data members for a given class.
Definition TRealData.h:30
static TClass * Class()
static TClass * Class()
static TClass * Class()
Describe one element (data member) to be Streamed.
Int_t GetType() const
const char * GetTypeName() const
static SequencePtr WriteMemberWiseActionsViaProxyGetter(TStreamerInfo *, TVirtualCollectionProxy *collectionProxy, TClass *)
static SequencePtr WriteMemberWiseActionsGetter(TStreamerInfo *info, TVirtualCollectionProxy *, TClass *)
static SequencePtr ConversionReadMemberWiseActionsViaProxyGetter(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *originalClass)
void Print(Option_t *="") const override
This method must be overridden when a class wants to print itself.
static SequencePtr WriteMemberWiseActionsCollectionCreator(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *)
static SequencePtr ReadMemberWiseActionsCollectionCreator(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *)
static SequencePtr ReadMemberWiseActionsGetter(TStreamerInfo *info, TVirtualCollectionProxy *, TClass *)
SequencePtr(*)(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *originalClass) SequenceGetter_t
static SequencePtr WriteMemberWiseActionsCollectionGetter(TStreamerInfo *info, TVirtualCollectionProxy *, TClass *)
static SequencePtr ReadMemberWiseActionsCollectionGetter(TStreamerInfo *info, TVirtualCollectionProxy *, TClass *)
static SequencePtr ReadMemberWiseActionsViaProxyGetter(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *)
Base class of the Configurations.
TVirtualStreamerInfo * fInfo
TStreamerInfo form which the action is derived.
UInt_t fElemId
Identifier of the TStreamerElement.
Describes a persistent version of a class.
TStreamerElement * GetElement(Int_t id) const override
T GetTypedValue(char *pointer, Int_t i, Int_t j, Int_t len) const
Return value of element i in object at pointer.
Int_t GetNelement() const
T GetTypedValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
Return value of element i in object number j in a TClonesArray and eventually element k in a sub-arra...
T GetTypedValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
Return value of element i in object number j in a TClonesArray and eventually element k in a sub-arra...
TClass * GetClass() const override
T GetTypedValueClones(TClonesArray *clones, Int_t i, Int_t j, Int_t k, Int_t eoffset) const
TStreamerElement * GetStreamerElement(const char *datamember, Int_t &offset) const override
Return the StreamerElement of "datamember" inside our class or any of its base classes.
UInt_t GetCheckSum() const override
static TClass * Class()
static TClass * Class()
static TClass * Class()
static TClass * Class()
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
static constexpr Ssiz_t kNPOS
Definition TString.h:278
const char * Data() const
Definition TString.h:376
@ kTrailing
Definition TString.h:276
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:931
TString & Remove(Ssiz_t pos)
Definition TString.h:685
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
static TClass * Class()
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
A TTree represents a columnar dataset.
Definition TTree.h:84
TStreamerInfo * BuildStreamerInfo(TClass *cl, void *pointer=nullptr, bool canOptimize=true)
Build StreamerInfo for class cl.
Definition TTree.cxx:2649
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition TTree.cxx:5299
Int_t GetDefaultEntryOffsetLen() const
Definition TTree.h:474
virtual TObjArray * GetListOfLeaves()
Definition TTree.h:544
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:446
TDirectory * GetDirectory() const
Definition TTree.h:477
@ kSplitCollectionOfPointers
Definition TTree.h:278
Int_t Debug() const
Definition TTree.h:444
virtual TBranchRef * GetBranchRef() const
Definition TTree.h:465
virtual Long64_t GetReadEntry() const
Definition TTree.h:564
Long64_t GetDebugMin() const
Definition TTree.h:476
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
char * GetObjectAt(UInt_t ind) const
void SetSize(UInt_t size)
Small helper class to generically acquire and release iterators.
void CreateIterators(void *collection, TVirtualCollectionProxy *proxy)
RAII helper class that ensures that PushProxy() / PopProxy() are called when entering / leaving a C++...
Defines a common interface to inspect/change the contents of an object that represents a collection.
@ kNeedDelete
The collection contains directly or indirectly (via other collection) some pointers that need explici...
virtual TClass * GetValueClass() const =0
If the value type is a user-defined class, return a pointer to the TClass representing the value type...
virtual Int_t GetCollectionType() const =0
Return the type of the proxied collection (see enumeration TClassEdit::ESTLType)
virtual Bool_t HasPointers() const =0
Return true if the content is of type 'pointer to'.
void CreateIterators(void *collection, TVirtualCollectionProxy *proxy)
Abstract Interface class describing Streamer information for one class.
virtual UInt_t GetCheckSum() const =0
@ kUChar
Equal to TDataType's kchar.
virtual TObjArray * GetElements() const =0
std::ostream & Info()
Definition hadd.cxx:171
const Int_t n
Definition legend1.C:16
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
@ kSTLmap
Definition ESTLType.h:33
@ kSTLunorderedmultiset
Definition ESTLType.h:43
@ kSTLend
Definition ESTLType.h:47
@ kSTLset
Definition ESTLType.h:35
@ kSTLmultiset
Definition ESTLType.h:36
@ kSTLvector
Definition ESTLType.h:30
@ kSTLunorderedmultimap
Definition ESTLType.h:45
@ kSTLunorderedset
Definition ESTLType.h:42
@ kSTLunorderedmap
Definition ESTLType.h:44
@ kNotSTL
Definition ESTLType.h:29
@ kSTLmultimap
Definition ESTLType.h:34
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
std::vector< TIDNode > TIDs
TCanvas * slash()
Definition slash.C:1
TMarker m
Definition textangle.C:8