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