Logo ROOT  
Reference Guide
TTreeReaderValue.cxx
Go to the documentation of this file.
1 // @(#)root/treeplayer:$Id$
2 // Author: Axel Naumann, 2011-09-28
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers and al. *
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 #include "TTreeReaderValue.h"
13 
14 #include "TTreeReader.h"
15 #include "TBranchClones.h"
16 #include "TBranchElement.h"
17 #include "TBranchRef.h"
18 #include "TBranchSTL.h"
19 #include "TBranchObject.h"
20 #include "TBranchProxyDirector.h"
21 #include "TClassEdit.h"
22 #include "TFriendElement.h"
23 #include "TFriendProxy.h"
24 #include "TLeaf.h"
25 #include "TTreeProxyGenerator.h"
26 #include "TRegexp.h"
27 #include "TStreamerInfo.h"
28 #include "TStreamerElement.h"
29 #include "TNtuple.h"
30 #include "TROOT.h"
31 #include <vector>
32 
33 // clang-format off
34 /**
35  * \class TTreeReaderValue
36  * \ingroup treeplayer
37  * \brief An interface for reading values stored in ROOT columnar datasets
38  *
39  * The TTreeReaderValue is a type-safe tool to be used in association with a TTreeReader
40  * to access the values stored in TTree, TNtuple and TChain datasets.
41  * TTreeReaderValue can be also used to access collections such as `std::vector`s or TClonesArray
42  * stored in columnar datasets but it is recommended to use TTreeReaderArray instead as it offers
43  * several advantages.
44  *
45  * See the documentation of TTreeReader for more details and examples.
46 */
47 // clang-format on
48 
50 
51 ////////////////////////////////////////////////////////////////////////////////
52 /// Construct a tree value reader and register it with the reader object.
53 
55  const char* branchname /*= 0*/,
56  TDictionary* dict /*= 0*/):
57  fHaveLeaf(0),
58  fHaveStaticClassOffsets(0),
59  fReadStatus(kReadNothingYet),
60  fBranchName(branchname),
61  fTreeReader(reader),
62  fDict(dict)
63 {
65 }
66 
67 ////////////////////////////////////////////////////////////////////////////////
68 /// Copy-construct.
69 
71  fHaveLeaf(rhs.fHaveLeaf),
72  fHaveStaticClassOffsets(rhs.fHaveStaticClassOffsets),
73  fReadStatus(rhs.fReadStatus),
74  fSetupStatus(rhs.fSetupStatus),
75  fBranchName(rhs.fBranchName),
76  fLeafName(rhs.fLeafName),
77  fTreeReader(rhs.fTreeReader),
78  fDict(rhs.fDict),
79  fProxy(rhs.fProxy),
80  fLeaf(rhs.fLeaf),
81  fStaticClassOffsets(rhs.fStaticClassOffsets)
82 {
84 }
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 /// Copy-assign.
88 
91  if (&rhs != this) {
92  fHaveLeaf = rhs.fHaveLeaf;
93  fHaveStaticClassOffsets = rhs.fHaveStaticClassOffsets;
94  fBranchName = rhs.fBranchName;
95  fLeafName = rhs.fLeafName;
96  if (fTreeReader != rhs.fTreeReader) {
97  if (fTreeReader)
98  fTreeReader->DeregisterValueReader(this);
99  fTreeReader = rhs.fTreeReader;
100  RegisterWithTreeReader();
101  }
102  fDict = rhs.fDict;
103  fProxy = rhs.fProxy;
104  fLeaf = rhs.fLeaf;
105  fSetupStatus = rhs.fSetupStatus;
106  fReadStatus = rhs.fReadStatus;
107  fStaticClassOffsets = rhs.fStaticClassOffsets;
108  }
109  return *this;
110 }
111 
112 ////////////////////////////////////////////////////////////////////////////////
113 /// Unregister from tree reader, cleanup.
114 
116 {
117  if (fTreeReader) fTreeReader->DeregisterValueReader(this);
118  R__ASSERT((fLeafName.Length() == 0 ) == !fHaveLeaf
119  && "leafness disagreement");
120  R__ASSERT(fStaticClassOffsets.empty() == !fHaveStaticClassOffsets
121  && "static class offset disagreement");
122 }
123 
124 ////////////////////////////////////////////////////////////////////////////////
125 /// Register with tree reader.
126 
128  if (fTreeReader) {
129  if (!fTreeReader->RegisterValueReader(this)) {
130  fTreeReader = nullptr;
131  }
132  }
133 }
134 
135 ////////////////////////////////////////////////////////////////////////////////
136 /// Try to read the value from the TBranchProxy, returns
137 /// the status of the read.
138 
139 
140 
141 template <ROOT::Internal::TTreeReaderValueBase::BranchProxyRead_t Func>
143 {
144  if ((fProxy->*Func)()) {
145  fReadStatus = kReadSuccess;
146  } else {
147  fReadStatus = kReadError;
148  }
149  return fReadStatus;
150 }
151 
154  if (!fProxy) return kReadNothingYet;
155  if (fProxy->IsInitialized() || fProxy->Setup()) {
156 
157  using EReadType = ROOT::Detail::TBranchProxy::EReadType;
158  using TBranchPoxy = ROOT::Detail::TBranchProxy;
159 
160  EReadType readtype = EReadType::kNoDirector;
161  if (fProxy) readtype = fProxy->GetReadType();
162 
163  switch (readtype) {
164  case EReadType::kNoDirector:
165  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoDirector>;
166  break;
167  case EReadType::kReadParentNoCollection:
168  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadParentNoCollection>;
169  break;
170  case EReadType::kReadParentCollectionNoPointer:
171  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadParentCollectionNoPointer>;
172  break;
173  case EReadType::kReadParentCollectionPointer:
174  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadParentCollectionPointer>;
175  break;
176  case EReadType::kReadNoParentNoBranchCountCollectionPointer:
177  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentNoBranchCountCollectionPointer>;
178  break;
179  case EReadType::kReadNoParentNoBranchCountCollectionNoPointer:
180  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentNoBranchCountCollectionNoPointer>;
181  break;
182  case EReadType::kReadNoParentNoBranchCountNoCollection:
183  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentNoBranchCountNoCollection>;
184  break;
185  case EReadType::kReadNoParentBranchCountCollectionPointer:
186  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentBranchCountCollectionPointer>;
187  break;
188  case EReadType::kReadNoParentBranchCountCollectionNoPointer:
189  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentBranchCountCollectionNoPointer>;
190  break;
191  case EReadType::kReadNoParentBranchCountNoCollection:
192  fProxyReadFunc = &TTreeReaderValueBase::ProxyReadTemplate<&TBranchPoxy::ReadNoParentBranchCountNoCollection>;
193  break;
194  case EReadType::kDefault:
195  // intentional fall through.
196  default: fProxyReadFunc = &TTreeReaderValueBase::ProxyReadDefaultImpl;
197  }
198  return (this->*fProxyReadFunc)();
199  }
200 
201  // If somehow the Setup fails call the original Read to
202  // have the proper error handling (message only if the Setup fails
203  // and the current proxy entry is different than the TTree's current entry)
204  if (fProxy->Read()) {
205  fReadStatus = kReadSuccess;
206  } else {
207  fReadStatus = kReadError;
208  }
209  return fReadStatus;
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// Stringify the template argument.
214 std::string ROOT::Internal::TTreeReaderValueBase::GetElementTypeName(const std::type_info& ti) {
215  int err;
216  char* buf = TClassEdit::DemangleTypeIdName(ti, err);
217  std::string ret = buf;
218  free(buf);
219  return ret;
220 }
221 
222 ////////////////////////////////////////////////////////////////////////////////
223 /// The TTreeReader has switched to a new TTree. Update the leaf.
224 
226  // Since the TTree structure might have change, let's make sure we
227  // use the right reading function.
229 
230  if (!fHaveLeaf || !newTree) {
231  fLeaf = nullptr;
232  return;
233  }
234 
235  TBranch *myBranch = newTree->GetBranch(fBranchName);
236 
237  if (!myBranch) {
238  fReadStatus = kReadError;
239  Error("TTreeReaderValueBase::GetLeaf()", "Unable to get the branch from the tree");
240  return;
241  }
242 
243  fLeaf = myBranch->GetLeaf(fLeafName);
244  if (!fLeaf) {
245  Error("TTreeReaderValueBase::GetLeaf()", "Failed to get the leaf from the branch");
246  }
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 /// Returns the memory address of the object being read.
251 
253  if (ProxyRead() != kReadSuccess) return 0;
254 
255  if (fHaveLeaf){
256  if (GetLeaf()){
257  return fLeaf->GetValuePointer();
258  }
259  else {
260  fReadStatus = kReadError;
261  Error("TTreeReaderValueBase::GetAddress()", "Unable to get the leaf");
262  return 0;
263  }
264  }
265  if (fHaveStaticClassOffsets){ // Follow all the pointers
266  Byte_t *address = (Byte_t*)fProxy->GetWhere();
267 
268  for (unsigned int i = 0; i < fStaticClassOffsets.size() - 1; ++i){
269  address = *(Byte_t**)(address + fStaticClassOffsets[i]);
270  }
271 
272  return address + fStaticClassOffsets.back();
273  }
274  return (Byte_t*)fProxy->GetWhere();
275 }
276 
277 ////////////////////////////////////////////////////////////////////////////////
278 /// \brief Search a branch the name of which contains a "."
279 /// \param[out] myLeaf The leaf identified by the name if found (can be untouched).
280 /// \param[out] branchActualType Dictionary associated to the type of the leaf (can be untouched).
281 /// \param[out] errMsg The error message (can be untouched).
282 /// \return The address of the branch if found, nullptr otherwise
283 /// This method allows to efficiently search for branches which have names which
284 /// contain "dots", for example "w.v.a" or "v.a".
285 /// Therefore, it allows to support names such as v.a where the branch was
286 /// created with this syntax:
287 /// ```{.cpp}
288 /// myTree->Branch("v", &v, "a/I:b:/I")
289 /// ```
290 /// The method has some side effects, namely it can modify fSetupStatus, fProxy
291 /// and fStaticClassOffsets/fHaveStaticClassOffsets.
293 {
294  TRegexp leafNameExpression ("\\.[a-zA-Z0-9_]+$");
295  TString leafName (fBranchName(leafNameExpression));
296  TString branchName = fBranchName(0, fBranchName.Length() - leafName.Length());
297  auto branch = fTreeReader->GetTree()->GetBranch(branchName);
298  if (!branch){
299  std::vector<TString> nameStack;
300  nameStack.push_back(TString()); //Trust me
301  nameStack.push_back(leafName.Strip(TString::kBoth, '.'));
302  leafName = branchName(leafNameExpression);
303  branchName = branchName(0, branchName.Length() - leafName.Length());
304 
305  branch = fTreeReader->GetTree()->GetBranch(branchName);
306  if (!branch) branch = fTreeReader->GetTree()->GetBranch(branchName + ".");
307  if (leafName.Length()) nameStack.push_back(leafName.Strip(TString::kBoth, '.'));
308 
309  while (!branch && branchName.Contains(".")){
310  leafName = branchName(leafNameExpression);
311  branchName = branchName(0, branchName.Length() - leafName.Length());
312  branch = fTreeReader->GetTree()->GetBranch(branchName);
313  if (!branch) branch = fTreeReader->GetTree()->GetBranch(branchName + ".");
314  nameStack.push_back(leafName.Strip(TString::kBoth, '.'));
315  }
316 
317  if (branch && branch->IsA() == TBranchElement::Class()){
318  TBranchElement *myBranchElement = (TBranchElement*)branch;
319 
320  TString traversingBranch = nameStack.back();
321  nameStack.pop_back();
322 
323  bool found = true;
324 
325  TDataType *finalDataType = 0;
326 
327  std::vector<Long64_t> offsets;
328  Long64_t offset = 0;
329  TClass *elementClass = 0;
330 
331  TObjArray *myObjArray = myBranchElement->GetInfo()->GetElements();
332  TVirtualStreamerInfo *myInfo = myBranchElement->GetInfo();
333 
334  while (nameStack.size() && found){
335  found = false;
336 
337  for (int i = 0; i < myObjArray->GetEntries(); ++i){
338 
339  TStreamerElement *tempStreamerElement = (TStreamerElement*)myObjArray->At(i);
340 
341  if (!strcmp(tempStreamerElement->GetName(), traversingBranch.Data())){
342  offset += myInfo->GetElementOffset(i);
343 
344  traversingBranch = nameStack.back();
345  nameStack.pop_back();
346 
347  elementClass = tempStreamerElement->GetClass();
348  if (elementClass) {
349  myInfo = elementClass->GetStreamerInfo(0);
350  myObjArray = myInfo->GetElements();
351  // FIXME: this is odd, why is 'i' not also reset????
352  }
353  else {
354  finalDataType = TDataType::GetDataType((EDataType)tempStreamerElement->GetType());
355  if (!finalDataType) {
356  TDictionary* seType = TDictionary::GetDictionary(tempStreamerElement->GetTypeName());
357  if (seType && seType->IsA() == TDataType::Class()) {
358  finalDataType = TDataType::GetDataType((EDataType)((TDataType*)seType)->GetType());
359  }
360  }
361  }
362 
363  if (tempStreamerElement->IsaPointer()){
364  offsets.push_back(offset);
365  offset = 0;
366  }
367 
368  found = true;
369  break;
370  }
371  }
372  }
373 
374  offsets.push_back(offset);
375 
376  if (found){
377  fStaticClassOffsets = offsets;
378  fHaveStaticClassOffsets = 1;
379 
380  if (fDict != finalDataType && fDict != elementClass){
381  errMsg = "Wrong data type ";
382  errMsg += finalDataType ? finalDataType->GetName() : elementClass ? elementClass->GetName() : "UNKNOWN";
383  fSetupStatus = kSetupMismatch;
384  fProxy = 0;
385  return nullptr;
386  }
387  }
388  }
389 
390 
391  if (!fHaveStaticClassOffsets) {
392  errMsg = "The tree does not have a branch called ";
393  errMsg += fBranchName;
394  errMsg += ". You could check with TTree::Print() for available branches.";
395  fSetupStatus = kSetupMissingBranch;
396  fProxy = 0;
397  return nullptr;
398  }
399  }
400  else {
401  myLeaf = branch->GetLeaf(TString(leafName(1, leafName.Length())));
402  if (!myLeaf){
403  errMsg = "The tree does not have a branch, nor a sub-branch called ";
404  errMsg += fBranchName;
405  errMsg += ". You could check with TTree::Print() for available branches.";
406  fSetupStatus = kSetupMissingBranch;
407  fProxy = 0;
408  return nullptr;
409  }
410  else {
411  TDataType *tempDict = gROOT->GetType(myLeaf->GetTypeName());
412  if (tempDict && fDict->IsA() == TDataType::Class() && tempDict->GetType() == ((TDataType*)fDict)->GetType()) {
413  //fLeafOffset = myLeaf->GetOffset() / 4;
414  branchActualType = fDict;
415  fLeaf = myLeaf;
416  fBranchName = branchName;
417  fLeafName = leafName(1, leafName.Length());
418  fHaveLeaf = fLeafName.Length() > 0;
419  fSetupStatus = kSetupMatchLeaf;
420  }
421  else {
422  errMsg = "Leaf of type ";
423  errMsg += myLeaf->GetTypeName();
424  errMsg += " cannot be read by TTreeReaderValue<";
425  errMsg += fDict->GetName();
426  errMsg += ">.";
427  fSetupStatus = kSetupMismatch;
428  return nullptr;
429  }
430  }
431  }
432 
433  return branch;
434 }
435 
436 ////////////////////////////////////////////////////////////////////////////////
437 /// Create the proxy object for our branch.
438 
440 
441  constexpr const char* errPrefix = "TTreeReaderValueBase::CreateProxy()";
442 
443  if (fProxy) {
444  return;
445  }
446 
447  fSetupStatus = kSetupInternalError; // Fallback; set to something concrete below.
448  if (!fTreeReader) {
449  Error(errPrefix, "TTreeReader object not set / available for branch %s!",
450  fBranchName.Data());
451  fSetupStatus = kSetupTreeDestructed;
452  return;
453  }
454 
455  auto branchFromFullName = fTreeReader->GetTree()->GetBranch(fBranchName);
456  if (branchFromFullName == nullptr) // use the slower but more thorough FindBranch as fallback
457  branchFromFullName = fTreeReader->GetTree()->FindBranch(fBranchName);
458 
459  if (!fDict) {
460  const char* brDataType = "{UNDETERMINED}";
461  if (branchFromFullName) {
462  TDictionary* brDictUnused = 0;
463  brDataType = GetBranchDataType(branchFromFullName, brDictUnused, fDict);
464  }
465  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.",
466  GetDerivedTypeName(), fBranchName.Data(), brDataType);
467  fSetupStatus = kSetupMissingDictionary;
468  return;
469  }
470 
471  // Search for the branchname, determine what it contains, and wire the
472  // TBranchProxy representing it to us so we can access its data.
473 
474  TNamedBranchProxy* namedProxy = fTreeReader->FindProxy(fBranchName);
475  if (namedProxy && namedProxy->GetDict() == fDict) {
476  fProxy = namedProxy->GetProxy();
477  // But go on: we need to set fLeaf etc!
478  }
479 
480  const std::string originalBranchName = fBranchName.Data();
481 
482  TLeaf *myLeaf = nullptr;
483  TDictionary* branchActualType = nullptr;
484  std::string errMsg;
485 
486  TBranch *branch = nullptr;
487  // If the branch name contains at least a dot, we analyse it in detail and
488  // we give priority to the branch identified over the one which is found
489  // with the TTree::GetBranch method. This allows to correctly pick the desired
490  // branch in cases where a TTree has two branches, one called for example
491  // "w.v.a" and another one called "v.a".
492  // This behaviour is described in ROOT-9312.
493  if (fBranchName.Contains(".")) {
494  branch = SearchBranchWithCompositeName(myLeaf, branchActualType, errMsg);
495  // In rare cases where leaves contain the name of the branch as part of their
496  // name and a dot in the branch name (such as: branch "b." and leaf "b.a")
497  // the previous method may return the branch name ("b.") rather than the
498  // leaf name ("b.a") as we expect.
499  // For these cases, we do not have to give priority to the previously
500  // identified branch since we are in a different situation.
501  // This behaviour is described in ROOT-9757.
502  if (branch && branch->IsA() == TBranchElement::Class() && branchFromFullName){
503  branch = branchFromFullName;
504  fStaticClassOffsets = {};
505  fHaveStaticClassOffsets = 0;
506  }
507  }
508 
509  if (!branch) {
510  // We had an error, the branch name had no "." or we simply did not find anything.
511  // We check if we had a branch found with the full name with a dot in it.
512  branch = branchFromFullName;
513  if (!branch) {
514  // Also that one was empty. We need to error out. We do it properly: at
515  // first we check if the routine to find branches with names with a "."
516  // provided a specific error message. If not, we go with a generic message.
517  if (errMsg.empty()) {
518  errMsg = "The tree does not have a branch called ";
519  errMsg += fBranchName.Data();
520  errMsg += ". You could check with TTree::Print() for available branches.";
521  }
522 #if !defined(_MSC_VER)
523 #pragma GCC diagnostic push
524 #pragma GCC diagnostic ignored "-Wformat-security"
525 #endif
526  Error(errPrefix, errMsg.c_str());
527 #if !defined(_MSC_VER)
528 #pragma GCC diagnostic pop
529 #endif
530  return;
531  } else {
532  // The branch found with the simplest search approach was successful.
533  // We reset the state, we continue
534  fSetupStatus = kSetupInternalError;
535  fStaticClassOffsets = {};
536  fHaveStaticClassOffsets = 0;
537  }
538  }
539 
540  if (!myLeaf && !fHaveStaticClassOffsets) {
541  // The following two lines cannot be swapped. The GetBranchDataType can
542  // change the value of branchActualType
543  const char* branchActualTypeName = GetBranchDataType(branch, branchActualType, fDict);
544  if (!branchActualType) {
545  Error(errPrefix, "The branch %s contains data of type %s, which does not have a dictionary.",
546  fBranchName.Data(), branchActualTypeName ? branchActualTypeName : "{UNDETERMINED TYPE}");
547  fProxy = 0;
548  return;
549  }
550 
551  // Check if the dictionaries are TClass instances and if there is inheritance
552  // because in this case, we can read the values.
553  auto dictAsClass = dynamic_cast<TClass*>(fDict);
554  auto branchActualTypeAsClass = dynamic_cast<TClass*>(branchActualType);
555  auto inheritance = dictAsClass && branchActualTypeAsClass && branchActualTypeAsClass->InheritsFrom(dictAsClass);
556 
557  if (fDict != branchActualType && !inheritance) {
558  TDataType *dictdt = dynamic_cast<TDataType*>(fDict);
559  TDataType *actualdt = dynamic_cast<TDataType*>(branchActualType);
560  bool complainAboutMismatch = true;
561  if (dictdt && actualdt) {
562  if (dictdt->GetType() > 0 && dictdt->GetType() == actualdt->GetType()) {
563  // Same numerical type but different TDataType, likely Long64_t
564  complainAboutMismatch = false;
565  } else if ((actualdt->GetType() == kDouble32_t && dictdt->GetType() == kDouble_t)
566  || (actualdt->GetType() == kFloat16_t && dictdt->GetType() == kFloat_t)) {
567  // Double32_t and Float16_t never "decay" to their underlying type;
568  // we need to identify them manually here (ROOT-8731).
569  complainAboutMismatch = false;
570  }
571  }
572  if (complainAboutMismatch) {
573  Error(errPrefix,
574  "The branch %s contains data of type %s. It cannot be accessed by a TTreeReaderValue<%s>",
575  fBranchName.Data(), branchActualType->GetName(),
576  fDict->GetName());
577  return;
578  }
579  }
580  }
581 
582  if (!namedProxy) {
583  // Search for the branchname, determine what it contains, and wire the
584  // TBranchProxy representing it to us so we can access its data.
585  // A proxy for branch must not have been created before (i.e. check
586  // fProxies before calling this function!)
587 
588  TString membername;
589 
590  bool isTopLevel = branch->GetMother() == branch;
591  if (!isTopLevel) {
592  membername = strrchr(branch->GetName(), '.');
593  if (membername.IsNull()) {
594  membername = branch->GetName();
595  }
596  }
597  auto director = fTreeReader->fDirector;
598  // Determine if the branch is actually in a Friend TTree and if so which.
599  if (branch->GetTree() != fTreeReader->GetTree()->GetTree()) {
600  // It is in a friend, let's find the 'index' in the list of friend ...
601  int index = -1;
602  int current = 0;
603  TFriendElement *fe_found = nullptr;
604  for(auto fe : TRangeDynCast<TFriendElement>( fTreeReader->GetTree()->GetTree()->GetListOfFriends())) {
605  if (branch->GetTree() == fe->GetTree()) {
606  index = current;
607  fe_found = fe;
608  break;
609  }
610  ++current;
611  }
612  if (index == -1) {
613  Error(errPrefix, "The branch %s is contained in a Friend TTree that is not directly attached to the main.\n"
614  "This is not yet supported by TTreeReader.",
615  fBranchName.Data());
616  return;
617  }
618  const char *localBranchName = originalBranchName.c_str();
619  if (branch != branch->GetTree()->GetBranch(localBranchName)) {
620  // Try removing the name of the TTree.
621  auto len = strlen( branch->GetTree()->GetName());
622  if (strncmp(localBranchName, branch->GetTree()->GetName(), len) == 0
623  && localBranchName[len] == '.'
624  && branch != branch->GetTree()->GetBranch(localBranchName+len+1)) {
625  localBranchName = localBranchName + len + 1;
626  } else {
627  len = strlen(fe_found->GetName());
628  if (strncmp(localBranchName, fe_found->GetName(), len) == 0
629  && localBranchName[len] == '.'
630  && branch != branch->GetTree()->GetBranch(localBranchName+len+1)) {
631  localBranchName = localBranchName + len + 1;
632  }
633  }
634  }
635  TFriendProxy *feproxy = nullptr;
636  if ((size_t)index < fTreeReader->fFriendProxies.size()) {
637  feproxy = fTreeReader->fFriendProxies.at(index);
638  }
639  if (!feproxy) {
640  feproxy = new ROOT::Internal::TFriendProxy(director, fTreeReader->GetTree(), index);
641  fTreeReader->fFriendProxies.resize(index+1);
642  fTreeReader->fFriendProxies.at(index) = feproxy;
643  }
644  namedProxy = new TNamedBranchProxy(feproxy->GetDirector(), branch, originalBranchName.c_str(), branch->GetName(), membername);
645  } else {
646  namedProxy = new TNamedBranchProxy(director, branch, originalBranchName.c_str(), membername);
647  }
648  fTreeReader->AddProxy(namedProxy);
649  }
650 
651  // Update named proxy's dictionary
652  if (!namedProxy->GetDict())
653  namedProxy->SetDict(fDict);
654 
655  fProxy = namedProxy->GetProxy();
656  if (fProxy) {
657  fSetupStatus = kSetupMatch;
658  } else {
659  fSetupStatus = kSetupMismatch;
660  }
661 }
662 
663 ////////////////////////////////////////////////////////////////////////////////
664 /// Retrieve the type of data stored by branch; put its dictionary into
665 /// dict, return its type name. If no dictionary is available, at least
666 /// its type name should be returned.
667 
669  TDictionary* &dict,
670  TDictionary const *curDict)
671 {
672  dict = 0;
673  if (branch->IsA() == TBranchElement::Class()) {
674  TBranchElement* brElement = (TBranchElement*)branch;
675 
676  auto ResolveTypedef = [&]() -> void {
677  if (dict->IsA() != TDataType::Class())
678  return;
679  // Resolve the typedef.
680  dict = TDictionary::GetDictionary(((TDataType*)dict)->GetTypeName());
681  if (dict->IsA() != TDataType::Class()) {
682  // Might be a class.
683  if (dict != curDict) {
684  dict = TClass::GetClass(brElement->GetTypeName());
685  }
686  if (dict != curDict) {
687  dict = brElement->GetCurrentClass();
688  }
689  }
690  };
691 
692  if (brElement->GetType() == TBranchElement::kSTLNode ||
693  brElement->GetType() == TBranchElement::kLeafNode ||
694  brElement->GetType() == TBranchElement::kObjectNode) {
695 
696  TStreamerInfo *streamerInfo = brElement->GetInfo();
697  Int_t id = brElement->GetID();
698 
699  if (id >= 0){
700  TStreamerElement *element = (TStreamerElement*)streamerInfo->GetElements()->At(id);
701  if (element->IsA() == TStreamerSTL::Class()){
702  TStreamerSTL *myStl = (TStreamerSTL*)element;
703  dict = myStl->GetClass();
704  return 0;
705  }
706  }
707 
708  if (brElement->GetType() == 3 || brElement->GetType() == 4) {
709  dict = brElement->GetCurrentClass();
710  return brElement->GetTypeName();
711  }
712 
713  if (brElement->GetTypeName())
714  dict = TDictionary::GetDictionary(brElement->GetTypeName());
715 
716  if (dict)
717  ResolveTypedef();
718  else
719  dict = brElement->GetCurrentClass();
720 
721  return brElement->GetTypeName();
722  } else if (brElement->GetType() == TBranchElement::kClonesNode) {
723  dict = TClonesArray::Class();
724  return "TClonesArray";
725  } else if (brElement->GetType() == 31
726  || brElement->GetType() == 41) {
727  // it's a member, extract from GetClass()'s streamer info
728  Error("TTreeReaderValueBase::GetBranchDataType()", "Must use TTreeReaderArray to access a member of an object that is stored in a collection.");
729  } else if (brElement->GetType() == -1 && brElement->GetTypeName()) {
730  dict = TDictionary::GetDictionary(brElement->GetTypeName());
731  ResolveTypedef();
732  return brElement->GetTypeName();
733  } else {
734  Error("TTreeReaderValueBase::GetBranchDataType()", "Unknown type and class combination: %i, %s", brElement->GetType(), brElement->GetClassName());
735  }
736  return 0;
737  } else if (branch->IsA() == TBranch::Class()
738  || branch->IsA() == TBranchObject::Class()
739  || branch->IsA() == TBranchSTL::Class()) {
740  if (branch->GetTree()->IsA() == TNtuple::Class()){
742  return dict->GetName();
743  }
744  const char* dataTypeName = branch->GetClassName();
745  if ((!dataTypeName || !dataTypeName[0])
746  && branch->IsA() == TBranch::Class()) {
747  TLeaf *myLeaf = branch->GetLeaf(branch->GetName());
748  if (myLeaf){
749  TDictionary *myDataType = TDictionary::GetDictionary(myLeaf->GetTypeName());
750  if (myDataType && myDataType->IsA() == TDataType::Class()){
751  if (myLeaf->GetLeafCount() != nullptr || myLeaf->GetLenStatic() > 1) {
752  Error("TTreeReaderValueBase::GetBranchDataType()", "Must use TTreeReaderArray to read branch %s: it contains an array or a collection.", branch->GetName());
753  return 0;
754  }
755  dict = TDataType::GetDataType((EDataType)((TDataType*)myDataType)->GetType());
756  return myLeaf->GetTypeName();
757  }
758  }
759 
760  // leaflist. Can't represent.
761  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());
762  TIter iLeaves(branch->GetListOfLeaves());
763  TLeaf* leaf = 0;
764  while ((leaf = (TLeaf*) iLeaves())) {
765  Error("TTreeReaderValueBase::GetBranchDataType()", " %s.%s", branch->GetName(), leaf->GetName());
766  }
767  return 0;
768  }
769  if (dataTypeName) dict = TDictionary::GetDictionary(dataTypeName);
770  return dataTypeName;
771  } else if (branch->IsA() == TBranchClones::Class()) {
772  dict = TClonesArray::Class();
773  return "TClonesArray";
774  } else if (branch->IsA() == TBranchRef::Class()) {
775  // Can't represent.
776  Error("TTreeReaderValueBase::GetBranchDataType()", "The branch %s is a TBranchRef and cannot be represented as a C++ type.", branch->GetName());
777  return 0;
778  } else {
779  Error("TTreeReaderValueBase::GetBranchDataType()", "The branch %s is of type %s - something that is not handled yet.", branch->GetName(), branch->IsA()->GetName());
780  return 0;
781  }
782 
783  return 0;
784 }
TClass::GetStreamerInfo
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:4567
ROOT::Internal::TTreeReaderValueBase::fDict
TDictionary * fDict
Definition: TTreeReaderValue.h:128
kDouble_t
@ kDouble_t
Definition: TDataType.h:31
TBranchElement::GetType
Int_t GetType() const
Definition: TBranchElement.h:203
ROOT::Detail::TBranchProxy::GetReadType
EReadType GetReadType()
Definition: TBranchProxy.h:189
TVirtualStreamerInfo::GetElementOffset
virtual Int_t GetElementOffset(Int_t id) const =0
ROOT::Internal::TTreeReaderValueBase::RegisterWithTreeReader
void RegisterWithTreeReader()
Register with tree reader.
Definition: TTreeReaderValue.cxx:127
TBranch::GetLeaf
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1963
ROOT::Internal::TTreeReaderValueBase::fStaticClassOffsets
std::vector< Long64_t > fStaticClassOffsets
Definition: TTreeReaderValue.h:131
TBranchElement::GetID
Int_t GetID() const
Definition: TBranchElement.h:195
TObjArray
An array of TObjects.
Definition: TObjArray.h:37
TTreeReaderValue.h
TStreamerElement::GetTypeName
const char * GetTypeName() const
Definition: TStreamerElement.h:123
TStreamerInfo.h
TBranchRef.h
TString::Strip
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
TBranchElement
A Branch for the case of an object.
Definition: TBranchElement.h:39
ROOT::Internal::TTreeReaderValueBase::NotifyNewTree
void NotifyNewTree(TTree *newTree)
The TTreeReader has switched to a new TTree. Update the leaf.
Definition: TTreeReaderValue.cxx:225
ROOT::Internal::TNamedBranchProxy::SetDict
void SetDict(TDictionary *dict)
Definition: TTreeReaderUtils.h:58
TBranchElement::GetCurrentClass
TClass * GetCurrentClass()
Return a pointer to the current type of the data member corresponding to branch element.
Definition: TBranchElement.cxx:2514
ROOT::Internal::TTreeReaderValueBase::fReadStatus
EReadStatus fReadStatus
Definition: TTreeReaderValue.h:123
ROOT::Internal::TFriendProxy::GetDirector
TBranchProxyDirector * GetDirector()
Definition: TFriendProxy.h:31
TString::Data
const char * Data() const
Definition: TString.h:369
ClassImp
#define ClassImp(name)
Definition: Rtypes.h:364
ROOT::Internal::TTreeReaderValueBase::GetElementTypeName
static std::string GetElementTypeName(const std::type_info &ti)
Stringify the template argument.
Definition: TTreeReaderValue.cxx:214
TStreamerElement.h
TDataType::GetType
Int_t GetType() const
Definition: TDataType.h:68
TBranchElement::GetTypeName
virtual const char * GetTypeName() const
Return type name of element in the branch.
Definition: TBranchElement.cxx:2819
Long64_t
long long Long64_t
Definition: RtypesCore.h:73
TTree
A TTree represents a columnar dataset.
Definition: TTree.h:79
TLeaf::GetTypeName
virtual const char * GetTypeName() const
Definition: TLeaf.h:138
TStreamerElement::IsaPointer
virtual Bool_t IsaPointer() const
Definition: TStreamerElement.h:129
Byte_t
unsigned char Byte_t
Definition: RtypesCore.h:64
ROOT::Internal::TTreeReaderValueBase::fSetupStatus
ESetupStatus fSetupStatus
Definition: TTreeReaderValue.h:124
TString::Contains
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:624
TObjArray::GetEntries
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:523
TString::Length
Ssiz_t Length() const
Definition: TString.h:410
TFriendElement
A TFriendElement TF describes a TTree object TF in a file.
Definition: TFriendElement.h:33
TRangeDynCast
TRangeDynCast is an adaptater class that allows the typed iteration through a TCollection.
Definition: TCollection.h:411
ROOT::Internal::TTreeReaderValueBase::fLeafName
TString fLeafName
Definition: TTreeReaderValue.h:126
TObjArray::At
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
TFriendElement.h
TBranch::GetClassName
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition: TBranch.cxx:1311
ROOT::Internal::TTreeReaderValueBase::fHaveStaticClassOffsets
int fHaveStaticClassOffsets
Definition: TTreeReaderValue.h:122
ROOT::Internal::TTreeReaderValueBase::SearchBranchWithCompositeName
TBranch * SearchBranchWithCompositeName(TLeaf *&myleaf, TDictionary *&branchActualType, std::string &err)
Search a branch the name of which contains a ".".
Definition: TTreeReaderValue.cxx:292
TString
Basic string class.
Definition: TString.h:136
TBranchElement::kLeafNode
@ kLeafNode
Definition: TBranchElement.h:239
TDataType::GetDataType
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
Definition: TDataType.cxx:440
TVirtualStreamerInfo
Abstract Interface class describing Streamer information for one class.
Definition: TVirtualStreamerInfo.h:37
ROOT::Internal::TTreeReaderValueBase::fTreeReader
TTreeReader * fTreeReader
Definition: TTreeReaderValue.h:127
kFloat16_t
@ kFloat16_t
Definition: TDataType.h:33
ROOT::Internal::TTreeReaderValueBase::fHaveLeaf
int fHaveLeaf
Definition: TTreeReaderValue.h:121
ROOT::Internal::TNamedBranchProxy::GetDict
TDictionary * GetDict() const
Definition: TTreeReaderUtils.h:57
TString::kBoth
@ kBoth
Definition: TString.h:267
TNtuple.h
TROOT.h
TTree::GetTree
virtual TTree * GetTree() const
Definition: TTree.h:512
TBranchElement::GetInfo
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
Definition: TBranchElement.cxx:1020
ROOT::Detail::TBranchProxy::EReadType
EReadType
Definition: TBranchProxy.h:175
TBranch
A TTree is a list of TBranches.
Definition: TBranch.h:89
TTree::GetBranch
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5214
TRegexp.h
kDouble32_t
@ kDouble32_t
Definition: TDataType.h:31
TTreeReader.h
TClass::InheritsFrom
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4835
TBranchElement.h
TLeaf.h
ROOT::Internal::TTreeReaderValueBase::ProxyReadTemplate
ROOT::Internal::TTreeReaderValueBase::EReadStatus ProxyReadTemplate()
Try to read the value from the TBranchProxy, returns the status of the read.
Definition: TTreeReaderValue.cxx:142
TDataType
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
TStreamerInfo::GetElements
TObjArray * GetElements() const
Definition: TStreamerInfo.h:210
TStreamerInfo
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:44
TLeaf
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:57
TStreamerElement::GetClass
TClass * GetClass() const
Definition: TStreamerElement.h:109
ROOT::Internal::TNamedBranchProxy::GetProxy
const Detail::TBranchProxy * GetProxy() const
Definition: TTreeReaderUtils.h:55
TLeaf::GetLeafCount
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
Definition: TLeaf.h:120
TBranchSTL.h
TBranchElement::GetClassName
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition: TBranchElement.h:186
TTreeReader
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition: TTreeReader.h:44
ROOT::Internal::TFriendProxy
Definition: TFriendProxy.h:22
TStreamerElement::GetType
Int_t GetType() const
Definition: TStreamerElement.h:119
ROOT::Internal::TTreeReaderValueBase::fBranchName
TString fBranchName
Definition: TTreeReaderValue.h:125
ROOT::Internal::TTreeReaderValueBase::fProxy
Detail::TBranchProxy * fProxy
Definition: TTreeReaderValue.h:129
TClass::GetClass
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:2932
TBranchProxyDirector.h
TBranchClones.h
kFloat_t
@ kFloat_t
Definition: TDataType.h:31
TStreamerSTL
Definition: TStreamerElement.h:391
TLeaf::GetLenStatic
virtual Int_t GetLenStatic() const
Return the fixed length of this leaf.
Definition: TLeaf.h:131
TDictionary
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:167
TTreeProxyGenerator.h
TRegexp
Regular expression class.
Definition: TRegexp.h:31
ROOT::Detail::TBranchProxy
Base class for all the proxy object.
Definition: TBranchProxy.h:69
ROOT::Internal::TTreeReaderValueBase::operator=
TTreeReaderValueBase & operator=(const TTreeReaderValueBase &)
Copy-assign.
Definition: TTreeReaderValue.cxx:90
TBranch::GetMother
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:2035
TBranchElement::kObjectNode
@ kObjectNode
Definition: TBranchElement.h:245
TString::IsNull
Bool_t IsNull() const
Definition: TString.h:407
R__ASSERT
#define R__ASSERT(e)
Definition: TError.h:120
TClassEdit.h
ROOT::Internal::TTreeReaderValueBase::GetBranchDataType
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.
Definition: TTreeReaderValue.cxx:668
TClass
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
ROOT::Internal::TTreeReaderValueBase::GetAddress
void * GetAddress()
Returns the memory address of the object being read.
Definition: TTreeReaderValue.cxx:252
EDataType
EDataType
Definition: TDataType.h:28
ROOT::Internal::TTreeReaderValueBase::~TTreeReaderValueBase
virtual ~TTreeReaderValueBase()
Unregister from tree reader, cleanup.
Definition: TTreeReaderValue.cxx:115
TBranchElement::kSTLNode
@ kSTLNode
Definition: TBranchElement.h:247
TBranchElement::kClonesNode
@ kClonesNode
Definition: TBranchElement.h:246
TBranchObject.h
ROOT::Internal::TTreeReaderValueBase::fLeaf
TLeaf * fLeaf
Definition: TTreeReaderValue.h:130
ROOT::Internal::TTreeReaderValueBase::ProxyReadDefaultImpl
EReadStatus ProxyReadDefaultImpl()
Definition: TTreeReaderValue.cxx:153
TIter
Definition: TCollection.h:233
ROOT::Internal::TTreeReaderValueBase
Base class of TTreeReaderValue.
Definition: TTreeReaderValue.h:44
TClassEdit::ResolveTypedef
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
Definition: TClassEdit.cxx:1727
ROOT::Internal::TNamedBranchProxy
Definition: TTreeReaderUtils.h:43
ROOT::Internal::TTreeReaderValueBase::EReadStatus
EReadStatus
Definition: TTreeReaderValue.h:67
TNamed::GetName
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
ROOT::Internal::TTreeReaderValueBase::TTreeReaderValueBase
TTreeReaderValueBase(TTreeReader *reader, const char *branchname, TDictionary *dict)
Construct a tree value reader and register it with the reader object.
Definition: TTreeReaderValue.cxx:54
free
#define free
Definition: civetweb.c:1539
kDefault
@ kDefault
Definition: TSystem.h:229
Class
void Class()
Definition: Class.C:29
TBranch::GetListOfLeaves
TObjArray * GetListOfLeaves()
Definition: TBranch.h:243
TBranch::GetTree
TTree * GetTree() const
Definition: TBranch.h:248
TFriendProxy.h
TDictionary::GetDictionary
static TDictionary * GetDictionary(const char *name)
Definition: TDictionary.cxx:84
RooStats::HistFactory::Constraint::GetType
Type GetType(const std::string &Name)
Definition: Systematics.cxx:34
ROOT::Internal::TTreeReaderValueBase::CreateProxy
virtual void CreateProxy()
Create the proxy object for our branch.
Definition: TTreeReaderValue.cxx:439
TStreamerElement
Definition: TStreamerElement.h:33
TVirtualStreamerInfo::GetElements
virtual TObjArray * GetElements() const =0
gROOT
#define gROOT
Definition: TROOT.h:406
TClassEdit::DemangleTypeIdName
char * DemangleTypeIdName(const std::type_info &ti, int &errorCode)
Demangle in a portable way the type id name.
Definition: TClassEdit.cxx:2124
int
Error
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition: TError.cxx:187