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