54 const char* branchname ,
57 fHaveStaticClassOffsets(0),
58 fReadStatus(kReadNothingYet),
59 fBranchName(branchname),
70 fHaveLeaf(rhs.fHaveLeaf),
71 fHaveStaticClassOffsets(rhs.fHaveStaticClassOffsets),
72 fReadStatus(rhs.fReadStatus),
73 fSetupStatus(rhs.fSetupStatus),
74 fBranchName(rhs.fBranchName),
75 fLeafName(rhs.fLeafName),
76 fTreeReader(rhs.fTreeReader),
80 fStaticClassOffsets(rhs.fStaticClassOffsets)
97 fTreeReader->DeregisterValueReader(
this);
99 RegisterWithTreeReader();
116 if (fTreeReader) fTreeReader->DeregisterValueReader(
this);
117 R__ASSERT((fLeafName.Length() == 0 ) == !fHaveLeaf
118 &&
"leafness disagreement");
119 R__ASSERT(fStaticClassOffsets.empty() == !fHaveStaticClassOffsets
120 &&
"static class offset disagreement");
128 if (!fTreeReader->RegisterValueReader(
this)) {
129 fTreeReader =
nullptr;
140template <ROOT::Internal::TTreeReaderValueBase::BranchProxyRead_t Func>
143 if ((fProxy->*Func)()) {
144 fReadStatus = kReadSuccess;
146 fReadStatus = kReadError;
153 if (!fProxy)
return kReadNothingYet;
154 if (fProxy->IsInitialized() || fProxy->Setup()) {
159 EReadType readtype = EReadType::kNoDirector;
163 case EReadType::kNoDirector:
164 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoDirector>;
166 case EReadType::kReadParentNoCollection:
167 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadParentNoCollection>;
169 case EReadType::kReadParentCollectionNoPointer:
170 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadParentCollectionNoPointer>;
172 case EReadType::kReadParentCollectionPointer:
173 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadParentCollectionPointer>;
175 case EReadType::kReadNoParentNoBranchCountCollectionPointer:
176 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentNoBranchCountCollectionPointer>;
178 case EReadType::kReadNoParentNoBranchCountCollectionNoPointer:
179 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentNoBranchCountCollectionNoPointer>;
181 case EReadType::kReadNoParentNoBranchCountNoCollection:
182 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentNoBranchCountNoCollection>;
184 case EReadType::kReadNoParentBranchCountCollectionPointer:
185 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentBranchCountCollectionPointer>;
187 case EReadType::kReadNoParentBranchCountCollectionNoPointer:
188 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentBranchCountCollectionNoPointer>;
190 case EReadType::kReadNoParentBranchCountNoCollection:
191 fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentBranchCountNoCollection>;
197 return (this->*fProxyReadFunc)();
203 if (fProxy->Read()) {
204 fReadStatus = kReadSuccess;
206 fReadStatus = kReadError;
216 std::string ret = buf;
229 if (!fHaveLeaf || !newTree) {
237 fReadStatus = kReadError;
238 Error(
"TTreeReaderValueBase::GetLeaf()",
"Unable to get the branch from the tree");
242 fLeaf = myBranch->
GetLeaf(fLeafName);
244 Error(
"TTreeReaderValueBase::GetLeaf()",
"Failed to get the leaf from the branch");
252 if (ProxyRead() != kReadSuccess)
return 0;
256 return fLeaf->GetValuePointer();
259 fReadStatus = kReadError;
260 Error(
"TTreeReaderValueBase::GetAddress()",
"Unable to get the leaf");
264 if (fHaveStaticClassOffsets){
267 for (
unsigned int i = 0; i < fStaticClassOffsets.size() - 1; ++i){
268 address = *(
Byte_t**)(address + fStaticClassOffsets[i]);
271 return address + fStaticClassOffsets.back();
273 return (
Byte_t*)fProxy->GetWhere();
293 TRegexp leafNameExpression (
"\\.[a-zA-Z0-9_]+$");
294 TString leafName (fBranchName(leafNameExpression));
295 TString branchName = fBranchName(0, fBranchName.Length() - leafName.
Length());
296 auto branch = fTreeReader->GetTree()->GetBranch(branchName);
298 std::vector<TString> nameStack;
299 nameStack.push_back(
TString());
301 leafName = branchName(leafNameExpression);
302 branchName = branchName(0, branchName.
Length() - leafName.
Length());
304 branch = fTreeReader->GetTree()->GetBranch(branchName);
305 if (!branch) branch = fTreeReader->GetTree()->GetBranch(branchName +
".");
308 while (!branch && branchName.
Contains(
".")){
309 leafName = branchName(leafNameExpression);
310 branchName = branchName(0, branchName.
Length() - leafName.
Length());
311 branch = fTreeReader->GetTree()->GetBranch(branchName);
312 if (!branch) branch = fTreeReader->GetTree()->GetBranch(branchName +
".");
319 TString traversingBranch = nameStack.back();
320 nameStack.pop_back();
326 std::vector<Long64_t> offsets;
333 while (nameStack.size() && found){
336 for (
int i = 0; i < myObjArray->
GetEntries(); ++i){
340 if (!strcmp(tempStreamerElement->
GetName(), traversingBranch.
Data())){
343 traversingBranch = nameStack.back();
344 nameStack.pop_back();
346 elementClass = tempStreamerElement->
GetClass();
354 if (!finalDataType) {
363 offsets.push_back(offset);
373 offsets.push_back(offset);
376 fStaticClassOffsets = offsets;
377 fHaveStaticClassOffsets = 1;
379 if (fDict != finalDataType && fDict != elementClass){
380 errMsg =
"Wrong data type ";
381 errMsg += finalDataType ? finalDataType->
GetName() : elementClass ? elementClass->
GetName() :
"UNKNOWN";
382 fSetupStatus = kSetupMismatch;
390 if (!fHaveStaticClassOffsets) {
391 errMsg =
"The tree does not have a branch called ";
392 errMsg += fBranchName;
393 errMsg +=
". You could check with TTree::Print() for available branches.";
394 fSetupStatus = kSetupMissingBranch;
400 myLeaf = branch->GetLeaf(
TString(leafName(1, leafName.
Length())));
402 errMsg =
"The tree does not have a branch, nor a sub-branch called ";
403 errMsg += fBranchName;
404 errMsg +=
". You could check with TTree::Print() for available branches.";
405 fSetupStatus = kSetupMissingBranch;
413 branchActualType = fDict;
415 fBranchName = branchName;
416 fLeafName = leafName(1, leafName.
Length());
417 fHaveLeaf = fLeafName.Length() > 0;
418 fSetupStatus = kSetupMatchLeaf;
421 errMsg =
"Leaf of type ";
423 errMsg +=
" cannot be read by TTreeReaderValue<";
424 errMsg += fDict->GetName();
426 fSetupStatus = kSetupMismatch;
440 constexpr const char* errPrefix =
"TTreeReaderValueBase::CreateProxy()";
446 fSetupStatus = kSetupInternalError;
448 Error(errPrefix,
"TTreeReader object not set / available for branch %s!",
450 fSetupStatus = kSetupTreeDestructed;
454 auto branchFromFullName = fTreeReader->GetTree()->GetBranch(fBranchName);
457 const char* brDataType =
"{UNDETERMINED}";
458 if (branchFromFullName) {
460 brDataType = GetBranchDataType(branchFromFullName, brDictUnused, fDict);
462 Error(errPrefix,
"The template argument type T of %s accessing branch %s (which contains data of type %s) is not known to ROOT. You will need to create a dictionary for it.",
463 GetDerivedTypeName(), fBranchName.Data(), brDataType);
464 fSetupStatus = kSetupMissingDictionary;
472 if (namedProxy && namedProxy->
GetDict() == fDict) {
477 const std::string originalBranchName = fBranchName.Data();
479 TLeaf *myLeaf =
nullptr;
490 if (fBranchName.Contains(
".")) {
491 branch = SearchBranchWithCompositeName(myLeaf, branchActualType, errMsg);
500 branch = branchFromFullName;
501 fStaticClassOffsets = {};
502 fHaveStaticClassOffsets = 0;
509 branch = branchFromFullName;
514 if (errMsg.empty()) {
515 errMsg =
"The tree does not have a branch called ";
516 errMsg += fBranchName.Data();
517 errMsg +=
". You could check with TTree::Print() for available branches.";
519#if !defined(_MSC_VER)
520#pragma GCC diagnostic push
521#pragma GCC diagnostic ignored "-Wformat-security"
523 Error(errPrefix, errMsg.c_str());
524#if !defined(_MSC_VER)
525#pragma GCC diagnostic pop
531 fSetupStatus = kSetupInternalError;
532 fStaticClassOffsets = {};
533 fHaveStaticClassOffsets = 0;
537 if (!myLeaf && !fHaveStaticClassOffsets) {
540 const char* branchActualTypeName = GetBranchDataType(branch, branchActualType, fDict);
541 if (!branchActualType) {
542 Error(errPrefix,
"The branch %s contains data of type %s, which does not have a dictionary.",
543 fBranchName.Data(), branchActualTypeName ? branchActualTypeName :
"{UNDETERMINED TYPE}");
550 auto dictAsClass =
dynamic_cast<TClass*
>(fDict);
551 auto branchActualTypeAsClass =
dynamic_cast<TClass*
>(branchActualType);
552 auto inheritance = dictAsClass && branchActualTypeAsClass && branchActualTypeAsClass->
InheritsFrom(dictAsClass);
554 if (fDict != branchActualType && !inheritance) {
557 bool complainAboutMismatch =
true;
558 if (dictdt && actualdt) {
561 complainAboutMismatch =
false;
566 complainAboutMismatch =
false;
569 if (complainAboutMismatch) {
571 "The branch %s contains data of type %s. It cannot be accessed by a TTreeReaderValue<%s>",
572 fBranchName.Data(), branchActualType->
GetName(),
587 bool isTopLevel = branch->
GetMother() == branch;
589 membername = strrchr(branch->
GetName(),
'.');
590 if (membername.
IsNull()) {
591 membername = branch->
GetName();
594 auto director = fTreeReader->fDirector;
610 Error(errPrefix,
"The branch %s is contained in a Friend TTree that is not directly attached to the main.\n"
611 "This is not yet supported by TTreeReader.",
615 const char *localBranchName = originalBranchName.c_str();
619 if (strncmp(localBranchName, branch->
GetTree()->
GetName(), len) == 0
620 && localBranchName[len] ==
'.'
622 localBranchName = localBranchName + len + 1;
624 len = strlen(fe_found->
GetName());
625 if (strncmp(localBranchName, fe_found->
GetName(), len) == 0
626 && localBranchName[len] ==
'.'
628 localBranchName = localBranchName + len + 1;
633 if ((
size_t)index < fTreeReader->fFriendProxies.size()) {
634 feproxy = fTreeReader->fFriendProxies.at(index);
638 fTreeReader->fFriendProxies.resize(index+1);
639 fTreeReader->fFriendProxies.at(index) = feproxy;
643 namedProxy =
new TNamedBranchProxy(director, branch, originalBranchName.c_str(), membername);
645 fTreeReader->AddProxy(namedProxy);
654 fSetupStatus = kSetupMatch;
656 fSetupStatus = kSetupMismatch;
680 if (dict != curDict) {
683 if (dict != curDict) {
721 return "TClonesArray";
722 }
else if (brElement->
GetType() == 31
723 || brElement->
GetType() == 41) {
725 Error(
"TTreeReaderValueBase::GetBranchDataType()",
"Must use TTreeReaderArray to access a member of an object that is stored in a collection.");
731 Error(
"TTreeReaderValueBase::GetBranchDataType()",
"Unknown type and class combination: %i, %s", brElement->
GetType(), brElement->
GetClassName());
742 if ((!dataTypeName || !dataTypeName[0])
749 Error(
"TTreeReaderValueBase::GetBranchDataType()",
"Must use TTreeReaderArray to read branch %s: it contains an array or a collection.", branch->
GetName());
758 Error(
"TTreeReaderValueBase::GetBranchDataType()",
"The branch %s was created using a leaf list and cannot be represented as a C++ type. Please access one of its siblings using a TTreeReaderArray:", branch->
GetName());
761 while ((leaf = (
TLeaf*) iLeaves())) {
762 Error(
"TTreeReaderValueBase::GetBranchDataType()",
" %s.%s", branch->
GetName(), leaf->
GetName());
770 return "TClonesArray";
773 Error(
"TTreeReaderValueBase::GetBranchDataType()",
"The branch %s is a TBranchRef and cannot be represented as a C++ type.", branch->
GetName());
776 Error(
"TTreeReaderValueBase::GetBranchDataType()",
"The branch %s is of type %s - something that is not handled yet.", branch->
GetName(), branch->IsA()->
GetName());
void Error(const char *location, const char *msgfmt,...)
Base class for all the proxy object.
TBranchProxyDirector * GetDirector()
void SetDict(TDictionary *dict)
const Detail::TBranchProxy * GetProxy() const
TDictionary * GetDict() const
Base class of TTreeReaderValue.
void RegisterWithTreeReader()
Register with tree reader.
void NotifyNewTree(TTree *newTree)
The TTreeReader has switched to a new TTree. Update the leaf.
void * GetAddress()
Returns the memory address of the object being read.
static std::string GetElementTypeName(const std::type_info &ti)
Stringify the template argument.
ESetupStatus fSetupStatus
TTreeReaderValueBase(TTreeReader *reader, const char *branchname, TDictionary *dict)
Construct a tree value reader and register it with the reader object.
ROOT::Internal::TTreeReaderValueBase::EReadStatus ProxyReadTemplate()
Try to read the value from the TBranchProxy, returns the status of the read.
TTreeReader * fTreeReader
TTreeReaderValueBase & operator=(const TTreeReaderValueBase &)
Copy-assign.
virtual ~TTreeReaderValueBase()
Unregister from tree reader, cleanup.
EReadStatus ProxyReadDefaultImpl()
virtual void CreateProxy()
Create the proxy object for our branch.
int fHaveStaticClassOffsets
Detail::TBranchProxy * fProxy
std::vector< Long64_t > fStaticClassOffsets
TBranch * SearchBranchWithCompositeName(TLeaf *&myleaf, TDictionary *&branchActualType, std::string &err)
Search a branch the name of which contains a ".".
static const char * GetBranchDataType(TBranch *branch, TDictionary *&dict, TDictionary const *curDict)
Retrieve the type of data stored by branch; put its dictionary into dict, return its type name.
A Branch for the case of an object.
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
TClass * GetCurrentClass()
Return a pointer to the current type of the data member corresponding to branch element.
virtual const char * GetTypeName() const
Return type name of element in the branch.
A TTree is a list of TBranches.
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
TObjArray * GetListOfLeaves()
TBranch * GetMother() const
Get our top-level parent branch in the tree.
TClass instances represent classes, structs and namespaces in the ROOT type system.
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
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.
Basic data type descriptor (datatype information is obtained from CINT).
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
This class defines an abstract interface that must be implemented by all classes that contain diction...
static TDictionary * GetDictionary(const char *name)
A TFriendElement TF describes a TTree object TF in a file.
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
virtual const char * GetTypeName() const
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
virtual Int_t GetLenStatic() const
Return the fixed length of this leaf.
virtual const char * GetName() const
Returns name of object.
Int_t GetEntries() const
Return the number of objects in array (i.e.
TObject * At(Int_t idx) const
TRangeDynCast is an adaptater class that allows the typed iteration through a TCollection.
Regular expression class.
virtual Bool_t IsaPointer() const
const char * GetTypeName() const
TClass * GetClass() const
Describe Streamer information for one class version.
TObjArray * GetElements() const
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
const char * Data() const
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
A TTree represents a columnar dataset.
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
virtual TTree * GetTree() const
Abstract Interface class describing Streamer information for one class.
virtual TObjArray * GetElements() const =0
virtual Int_t GetElementOffset(Int_t id) const =0
Type GetType(const std::string &Name)
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
char * DemangleTypeIdName(const std::type_info &ti, int &errorCode)
Demangle in a portable way the type id name.