Logo ROOT   6.10/09
Reference Guide
TTreeReaderArray.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 "TTreeReaderArray.h"
13 
14 #include "TBranchClones.h"
15 #include "TBranchElement.h"
16 #include "TBranchRef.h"
17 #include "TBranchSTL.h"
18 #include "TBranchProxyDirector.h"
19 #include "TClassEdit.h"
20 #include "TLeaf.h"
21 #include "TROOT.h"
22 #include "TStreamerInfo.h"
23 #include "TStreamerElement.h"
24 #include "TTreeReader.h"
25 #include "TGenCollectionProxy.h"
26 #include "TRegexp.h"
27 
28 // pin vtable
30 
31 namespace {
32  using namespace ROOT::Internal;
33 
34  // Reader interface for clones arrays
35  class TClonesReader: public TVirtualCollectionReader {
36  public:
37  ~TClonesReader() {}
39  if (!proxy->Read()){
41  Error("TClonesReader::GetCA()", "Read error in TBranchProxy.");
42  return 0;
43  }
45  return (TClonesArray*) proxy->GetWhere();
46  }
47  virtual size_t GetSize(ROOT::Detail::TBranchProxy* proxy) {
48  TClonesArray *myClonesArray = GetCA(proxy);
49  if (myClonesArray){
50  return myClonesArray->GetEntries();
51  }
52  else return 0;
53  }
54  virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx) {
55  TClonesArray *myClonesArray = GetCA(proxy);
56  if (myClonesArray){
57  return myClonesArray->UncheckedAt(idx);
58  }
59  else return 0;
60  }
61  };
62 
63  // Reader interface for STL
64  class TSTLReader: public TVirtualCollectionReader {
65  public:
66  ~TSTLReader() {}
68  if (!proxy->Read()) {
70  Error("TSTLReader::GetCP()", "Read error in TBranchProxy.");
71  return 0;
72  }
73  if (!proxy->GetWhere()) {
74  Error("TSTLReader::GetCP()", "Logic error, proxy object not set in TBranchProxy.");
75  return 0;
76  }
78  return (TVirtualCollectionProxy*) proxy->GetCollection();
79  }
80 
81  virtual size_t GetSize(ROOT::Detail::TBranchProxy* proxy) {
82  TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
83  if (!myCollectionProxy) return 0;
84  return myCollectionProxy->Size();
85  }
86 
87  virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx) {
88  TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
89  if (!myCollectionProxy) return 0;
90  if (myCollectionProxy->HasPointers()){
91  return *(void**)myCollectionProxy->At(idx);
92  }
93  else {
94  return myCollectionProxy->At(idx);
95  }
96  }
97  };
98 
99  class TCollectionLessSTLReader : public TVirtualCollectionReader {
100  private:
101  TVirtualCollectionProxy *fLocalCollection;
102  public:
103  TCollectionLessSTLReader(TVirtualCollectionProxy *proxy) : fLocalCollection(proxy) {}
104 
106  if (!proxy->Read()) {
108  Error("TCollectionLessSTLReader::GetCP()", "Read error in TBranchProxy.");
109  return 0;
110  }
111  if (!proxy->GetWhere()) {
112  Error("TCollectionLessSTLReader::GetCP()", "Logic error, proxy object not set in TBranchProxy.");
113  return 0;
114  }
116  return fLocalCollection;
117  }
118 
119  virtual size_t GetSize(ROOT::Detail::TBranchProxy* proxy) {
120  TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
121  if (!myCollectionProxy) return 0;
122  TVirtualCollectionProxy::TPushPop ppRaii(myCollectionProxy, proxy->GetWhere());
123  return myCollectionProxy->Size();
124  }
125 
126  virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx) {
127  TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
128  if (!myCollectionProxy) return 0;
129  TVirtualCollectionProxy::TPushPop ppRaii(myCollectionProxy, proxy->GetWhere());
130  if (myCollectionProxy->HasPointers()){
131  return *(void**)myCollectionProxy->At(idx);
132  } else {
133  return myCollectionProxy->At(idx);
134  }
135  }
136  };
137 
138 
139  // Reader interface for leaf list
140  // SEE TTreeProxyGenerator.cxx:1319: '//We have a top level raw type'
141  class TObjectArrayReader: public TVirtualCollectionReader {
142  private:
143  Int_t fBasicTypeSize;
144  public:
145  TObjectArrayReader() : fBasicTypeSize(-1) { }
146  ~TObjectArrayReader() {}
148  if (!proxy->Read()){
150  Error("TObjectArrayReader::GetCP()", "Read error in TBranchProxy.");
151  return 0;
152  }
154  return (TVirtualCollectionProxy*) proxy->GetCollection();
155  }
156  virtual size_t GetSize(ROOT::Detail::TBranchProxy* proxy) {
157  TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
158  if (!myCollectionProxy) return 0;
159  return myCollectionProxy->Size();
160  }
161  virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx) {
162  if (!proxy->Read()) return 0;
163 
164  Int_t objectSize;
165  void *array = (void*)proxy->GetStart();
166 
167  if (fBasicTypeSize == -1){
168  TClass *myClass = proxy->GetClass();
169  if (!myClass){
170  Error("TObjectArrayReader::At()", "Cannot get class info from branch proxy.");
171  return 0;
172  }
173  objectSize = myClass->GetClassSize();
174  }
175  else {
176  objectSize = fBasicTypeSize;
177  }
178  return (void*)((Byte_t*)array + (objectSize * idx));
179  }
180 
181  void SetBasicTypeSize(Int_t size){
182  fBasicTypeSize = size;
183  }
184  };
185 
186  template <class BASE>
187  class TUIntOrIntReader: public BASE {
188  private:
189  // The index can be of type int or unsigned int.
190  TTreeReaderValue<Int_t> fSizeReader;
191  bool fIsUnsigned = false;
192 
193  protected:
194  template <class T>
195  TTreeReaderValue<T>& GetSizeReader() {
196  return reinterpret_cast<TTreeReaderValue<T>&>(fSizeReader);
197  }
198 
199  public:
200  template <class... ARGS>
201  TUIntOrIntReader(TTreeReader *treeReader, const char *leafName,
202  ARGS&&... args):
203  BASE(std::forward<ARGS>(args)...)
204  {
205  if (TLeaf* sizeLeaf = treeReader->GetTree()->FindLeaf(leafName)) {
206  fIsUnsigned = sizeLeaf->IsUnsigned();
207  if (fIsUnsigned) {
208  GetSizeReader<UInt_t>() = TTreeReaderValue<UInt_t>(*treeReader, leafName);
209  } else {
210  GetSizeReader<Int_t>() = TTreeReaderValue<Int_t>(*treeReader, leafName);
211  }
212  }
213  }
214 
215  size_t GetSize(ROOT::Detail::TBranchProxy* /*proxy*/) override {
216  if (fIsUnsigned)
217  return *GetSizeReader<UInt_t>();
218  return *GetSizeReader<Int_t>();
219  }
220  };
221 
222  class TArrayParameterSizeReader: public TUIntOrIntReader<TObjectArrayReader> {
223  public:
224  TArrayParameterSizeReader(TTreeReader *treeReader, const char *branchName):
225  TUIntOrIntReader<TObjectArrayReader>(treeReader, branchName) {}
226  };
227 
228  // Reader interface for fixed size arrays
229  class TArrayFixedSizeReader : public TObjectArrayReader {
230  private:
231  Int_t fSize;
232 
233  public:
234  TArrayFixedSizeReader(Int_t sizeArg) : fSize(sizeArg) {}
235 
236  virtual size_t GetSize(ROOT::Detail::TBranchProxy* /*proxy*/) { return fSize; }
237  };
238 
239  class TBasicTypeArrayReader : public TVirtualCollectionReader {
240  public:
241  ~TBasicTypeArrayReader() {}
242 
244  if (!proxy->Read()){
246  Error("TBasicTypeArrayReader::GetCP()", "Read error in TBranchProxy.");
247  return 0;
248  }
250  return (TVirtualCollectionProxy*) proxy->GetCollection();
251  }
252 
253  virtual size_t GetSize(ROOT::Detail::TBranchProxy* proxy){
254  TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
255  if (!myCollectionProxy) return 0;
256  return myCollectionProxy->Size();
257  }
258 
259  virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx){
260  TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
261  if (!myCollectionProxy) return 0;
262  return (Byte_t*)myCollectionProxy->At(idx) + proxy->GetOffset();
263  }
264  };
265 
266  class TBasicTypeClonesReader : public TClonesReader {
267  private:
268  Int_t fOffset;
269  public:
270  TBasicTypeClonesReader(Int_t offsetArg) : fOffset(offsetArg) {}
271 
272  virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx){
273  TClonesArray *myClonesArray = GetCA(proxy);
274  if (!myClonesArray) return 0;
275  return (Byte_t*)myClonesArray->At(idx) + fOffset;
276  }
277  };
278 
279  class TLeafReader : public TVirtualCollectionReader {
280  private:
281  TTreeReaderValueBase *fValueReader;
282  Int_t fElementSize;
283  public:
284  TLeafReader(TTreeReaderValueBase *valueReaderArg) : fValueReader(valueReaderArg), fElementSize(-1) {}
285 
286  virtual size_t GetSize(ROOT::Detail::TBranchProxy* /*proxy*/){
287  TLeaf *myLeaf = fValueReader->GetLeaf();
288  return myLeaf ? myLeaf->GetLen() : 0; // Error will be printed by GetLeaf
289  }
290 
291  virtual void* At(ROOT::Detail::TBranchProxy* /*proxy*/, size_t idx){
292  ProxyRead();
293  void *address = fValueReader->GetAddress();
294  if (fElementSize == -1){
295  TLeaf *myLeaf = fValueReader->GetLeaf();
296  if (!myLeaf) return 0; // Error will be printed by GetLeaf
297  fElementSize = myLeaf->GetLenType();
298  }
299  return (Byte_t*)address + (fElementSize * idx);
300  }
301 
302  protected:
303  void ProxyRead(){
304  fValueReader->ProxyRead();
305  }
306  };
307 
308  class TLeafParameterSizeReader: public TUIntOrIntReader<TLeafReader> {
309  public:
310  TLeafParameterSizeReader(TTreeReader *treeReader, const char *leafName,
311  TTreeReaderValueBase *valueReaderArg) :
312  TUIntOrIntReader<TLeafReader>(treeReader, leafName, valueReaderArg) {}
313 
314  size_t GetSize(ROOT::Detail::TBranchProxy* proxy) override {
315  ProxyRead();
316  return TUIntOrIntReader<TLeafReader>::GetSize(proxy);
317  }
318  };
319 }
320 
321 /** \class TTreeReaderArray
322 
323 Extracts array data from a TTree.
324 */
325 
327 
328 ////////////////////////////////////////////////////////////////////////////////
329 /// Create the proxy object for our branch.
330 
331 void ROOT::Internal::TTreeReaderArrayBase::CreateProxy()
332 {
333  if (fProxy) {
334  return;
335  }
336 
337  fSetupStatus = kSetupInternalError; // Fallback; set to something concrete below.
338  if (!fTreeReader) {
339  Error("TTreeReaderArrayBase::CreateProxy()", "TTreeReader object not set / available for branch %s!",
340  fBranchName.Data());
341  fSetupStatus = kSetupTreeDestructed;
342  return;
343  }
344  if (!fDict) {
345  TBranch* br = fTreeReader->GetTree()->GetBranch(fBranchName);
346  const char* brDataType = "{UNDETERMINED}";
347  if (br) {
348  TDictionary* dictUnused = 0;
349  brDataType = GetBranchDataType(br, dictUnused);
350  }
351  Error("TTreeReaderArrayBase::CreateProxy()", "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.",
352  GetDerivedTypeName(), fBranchName.Data(), brDataType);
353  fSetupStatus = kSetupMissingDictionary;
354  return;
355  }
356 
357  // Access a branch's collection content (not the collection itself)
358  // through a proxy.
359  // Search for the branchname, determine what it contains, and wire the
360  // TBranchProxy representing it to us so we can access its data.
361 
362  TDictionary* branchActualType = 0;
363  TBranch* branch = nullptr;
364  TLeaf *myLeaf = nullptr;
365  if (!GetBranchAndLeaf(branch, myLeaf, branchActualType))
366  return;
367 
368  if (!fDict) {
369  Error("TTreeReaderArrayBase::CreateProxy()",
370  "No dictionary for branch %s.", fBranchName.Data());
371  return;
372  }
373 
374  TNamedBranchProxy* namedProxy = fTreeReader->FindProxy(fBranchName);
375  if (namedProxy) {
376  if (namedProxy->GetContentDict() == fDict) {
377  fSetupStatus = kSetupMatch;
378  fProxy = namedProxy->GetProxy();
379  SetImpl(branch, myLeaf);
380  return;
381  }
382 
383  // Update named proxy's dictionary
384  if (!namedProxy->GetContentDict()) {
385  namedProxy->SetContentDict(fDict);
386  fProxy = namedProxy->GetProxy();
387  if (fProxy)
388  fSetupStatus = kSetupMatch;
389  } else {
390  Error("TTreeReaderArrayBase::CreateProxy()",
391  "Type ambiguity (want %s, have %s) for branch %s.",
392  fDict->GetName(), namedProxy->GetContentDict()->GetName(), fBranchName.Data());
393  }
394  }
395  else {
396  TString membername;
397 
398  bool isTopLevel = branch->GetMother() == branch;
399  if (!isTopLevel) {
400  membername = strrchr(branch->GetName(), '.');
401  if (membername.IsNull()) {
402  membername = branch->GetName();
403  }
404  }
405  namedProxy = new TNamedBranchProxy(fTreeReader->fDirector, branch, fBranchName, membername);
406  fTreeReader->AddProxy(namedProxy);
407  fProxy = namedProxy->GetProxy();
408  if (fProxy)
409  fSetupStatus = kSetupMatch;
410  else
411  fSetupStatus = kSetupMismatch;
412  }
413 
414  if (!myLeaf){
415  TString branchActualTypeName;
416  const char* nonCollTypeName = GetBranchContentDataType(branch, branchActualTypeName, branchActualType);
417  if (nonCollTypeName) {
418  Error("TTreeReaderArrayBase::CreateContentProxy()", "The branch %s contains data of type %s, which should be accessed through a TTreeReaderValue< %s >.",
419  fBranchName.Data(), nonCollTypeName, nonCollTypeName);
420  if (fSetupStatus == kSetupInternalError)
421  fSetupStatus = kSetupNotACollection;
422  fProxy = 0;
423  return;
424  }
425  if (!branchActualType) {
426  if (branchActualTypeName.IsNull()) {
427  Error("TTreeReaderArrayBase::CreateContentProxy()", "Cannot determine the type contained in the collection of branch %s. That's weird - please report!",
428  fBranchName.Data());
429  } else {
430  Error("TTreeReaderArrayBase::CreateContentProxy()", "The branch %s contains data of type %s, which does not have a dictionary.",
431  fBranchName.Data(), branchActualTypeName.Data());
432  if (fSetupStatus == kSetupInternalError)
433  fSetupStatus = kSetupMissingDictionary;
434  }
435  fProxy = 0;
436  return;
437  }
438 
439  if (fDict != branchActualType) {
440  Error("TTreeReaderArrayBase::CreateContentProxy()", "The branch %s contains data of type %s. It cannot be accessed by a TTreeReaderArray<%s>",
441  fBranchName.Data(), branchActualType->GetName(), fDict->GetName());
442  if (fSetupStatus == kSetupInternalError || fSetupStatus >= 0)
443  fSetupStatus = kSetupMismatch;
444 
445  // Update named proxy's dictionary
446  if (namedProxy && !namedProxy->GetContentDict()) {
447  namedProxy->SetContentDict(fDict);
448  }
449 
450  // fProxy = 0;
451  // return;
452  }
453  }
454 
455  SetImpl(branch, myLeaf);
456 }
457 
458 ////////////////////////////////////////////////////////////////////////////////
459 /// Determine the branch / leaf and its type; reset fProxy / fSetupStatus on error.
460 
462  TDictionary* &branchActualType) {
463  myLeaf = nullptr;
464  branch = fTreeReader->GetTree()->GetBranch(fBranchName);
465  if (branch)
466  return true;
467 
468  if (!fBranchName.Contains(".")) {
469  Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.", fBranchName.Data());
470  fSetupStatus = kSetupMissingBranch;
471  fProxy = 0;
472  return false;
473  }
474 
475  TRegexp leafNameExpression ("\\.[a-zA-Z0-9_]+$");
476  TString leafName (fBranchName(leafNameExpression));
477  TString branchName = fBranchName(0, fBranchName.Length() - leafName.Length());
478  branch = fTreeReader->GetTree()->GetBranch(branchName);
479  if (!branch){
480  Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.", fBranchName.Data());
481  fSetupStatus = kSetupMissingBranch;
482  fProxy = 0;
483  return false;
484  }
485 
486  myLeaf = branch->GetLeaf(TString(leafName(1, leafName.Length())));
487  if (!myLeaf){
488  Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "The tree does not have a branch, nor a sub-branch called %s. You could check with TTree::Print() for available branches.", fBranchName.Data());
489  fSetupStatus = kSetupMissingBranch;
490  fProxy = 0;
491  return false;
492  }
493 
494  TDictionary *tempDict = TDictionary::GetDictionary(myLeaf->GetTypeName());
495  if (!tempDict){
496  Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Failed to get the dictionary for %s.", myLeaf->GetTypeName());
497  fSetupStatus = kSetupMissingDictionary;
498  fProxy = 0;
499  return false;
500  }
501 
502  if (tempDict->IsA() == TDataType::Class() && TDictionary::GetDictionary(((TDataType*)tempDict)->GetTypeName()) == fDict){
503  //fLeafOffset = myLeaf->GetOffset() / 4;
504  branchActualType = fDict;
505  fLeaf = myLeaf;
506  fBranchName = branchName;
507  fLeafName = leafName(1, leafName.Length());
508  fSetupStatus = kSetupMatchLeaf;
509  }
510  else {
511  Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Leaf of type %s cannot be read by TTreeReaderValue<%s>.", myLeaf->GetTypeName(), fDict->GetName());
512  fProxy = 0;
513  fSetupStatus = kSetupMismatch;
514  return false;
515  }
516  return true;
517 }
518 
519 
520 
521 
522 ////////////////////////////////////////////////////////////////////////////////
523 /// Create the TVirtualCollectionReader object for our branch.
524 
526 {
527  if (fImpl)
528  return;
529 
530  // Access a branch's collection content (not the collection itself)
531  // through a proxy.
532  // Search for the branchname, determine what it contains, and wire the
533  // TBranchProxy representing it to us so we can access its data.
534  // A proxy for branch must not have been created before (i.e. check
535  // fProxies before calling this function!)
536 
537  if (myLeaf){
538  if (!myLeaf->GetLeafCount()){
539  fImpl = new TLeafReader(this);
540  }
541  else {
542  TString leafFullName = myLeaf->GetBranch()->GetName();
543  leafFullName += ".";
544  leafFullName += myLeaf->GetLeafCount()->GetName();
545  fImpl = new TLeafParameterSizeReader(fTreeReader, leafFullName.Data(), this);
546  }
547  fSetupStatus = kSetupMatchLeaf;
548  }
549  else if (branch->IsA() == TBranchElement::Class()) {
550  TBranchElement* branchElement = ((TBranchElement*)branch);
551 
552  TStreamerInfo *streamerInfo = branchElement->GetInfo();
553  Int_t id = branchElement->GetID();
554 
555  if (id >= 0){ // Not root node?
556  // Int_t offset = streamerInfo->GetOffsets()[id];
557  TStreamerElement *element = (TStreamerElement*)streamerInfo->GetElements()->At(id);
558  // Bool_t isPointer = element->IsaPointer();
559  // TClass *classPointer = element->GetClassPointer();
560 
561  if (fSetupStatus == kSetupInternalError)
562  fSetupStatus = kSetupMatch;
563  if (element->IsA() == TStreamerSTL::Class()){
564  fImpl = new TSTLReader();
565  }
566  else if (element->IsA() == TStreamerObject::Class()){
567  //fImpl = new TObjectArrayReader(); // BArray[12]
568 
569  if (element->GetClass() == TClonesArray::Class()){
570  fImpl = new TClonesReader();
571  }
572  else {
573  fImpl = new TArrayFixedSizeReader(element->GetArrayLength());
574  }
575  }
576  else if (element->IsA() == TStreamerLoop::Class()) {
577  fImpl = new TArrayParameterSizeReader(fTreeReader, branchElement->GetBranchCount()->GetName());
578  }
579  else if (element->IsA() == TStreamerBasicType::Class()){
580  if (branchElement->GetType() == TBranchElement::kSTLMemberNode){
581  fImpl = new TBasicTypeArrayReader();
582  }
583  else if (branchElement->GetType() == TBranchElement::kClonesMemberNode){
584  fImpl = new TBasicTypeClonesReader(element->GetOffset());
585  }
586  else {
587  fImpl = new TArrayFixedSizeReader(element->GetArrayLength());
588  ((TObjectArrayReader*)fImpl)->SetBasicTypeSize(((TDataType*)fDict)->Size());
589  }
590  }
591  else if (element->IsA() == TStreamerBasicPointer::Class()) {
592  fImpl = new TArrayParameterSizeReader(fTreeReader, branchElement->GetBranchCount()->GetName());
593  ((TArrayParameterSizeReader*)fImpl)->SetBasicTypeSize(((TDataType*)fDict)->Size());
594  }
595  else if (element->IsA() == TStreamerBase::Class()){
596  fImpl = new TClonesReader();
597  } else {
598  Error("TTreeReaderArrayBase::SetImpl()",
599  "Cannot read branch %s: unhandled streamer element type %s",
600  fBranchName.Data(), element->IsA()->GetName());
601  fSetupStatus = kSetupInternalError;
602  }
603  }
604  else { // We are at root node?
605  if (branchElement->GetClass()->GetCollectionProxy()){
606  fImpl = new TCollectionLessSTLReader(branchElement->GetClass()->GetCollectionProxy());
607  }
608  }
609  } else if (branch->IsA() == TBranch::Class()) {
610  TLeaf *topLeaf = branch->GetLeaf(branch->GetName());
611  if (!topLeaf) {
612  Error("TTreeReaderArrayBase::SetImpl", "Failed to get the top leaf from the branch");
613  fSetupStatus = kSetupMissingBranch;
614  return;
615  }
616  Int_t size = 0;
617  TLeaf *sizeLeaf = topLeaf->GetLeafCounter(size);
618  if (fSetupStatus == kSetupInternalError)
619  fSetupStatus = kSetupMatch;
620  if (!sizeLeaf) {
621  fImpl = new TArrayFixedSizeReader(size);
622  }
623  else {
624  fImpl = new TArrayParameterSizeReader(fTreeReader, sizeLeaf->GetName());
625  }
626  ((TObjectArrayReader*)fImpl)->SetBasicTypeSize(((TDataType*)fDict)->Size());
627  } else if (branch->IsA() == TBranchClones::Class()) {
628  Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchClones not implemented");
629  fSetupStatus = kSetupInternalError;
630  } else if (branch->IsA() == TBranchObject::Class()) {
631  Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchObject not implemented");
632  fSetupStatus = kSetupInternalError;
633  } else if (branch->IsA() == TBranchSTL::Class()) {
634  Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchSTL not implemented");
635  fImpl = new TSTLReader();
636  fSetupStatus = kSetupInternalError;
637  } else if (branch->IsA() == TBranchRef::Class()) {
638  Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchRef not implemented");
639  fSetupStatus = kSetupInternalError;
640  }
641 }
642 
643 ////////////////////////////////////////////////////////////////////////////////
644 /// Access a branch's collection content (not the collection itself)
645 /// through a proxy.
646 /// Retrieve the type of data contained in the collection stored by branch;
647 /// put its dictionary into dict, If there is no dictionary, put its type
648 /// name into contentTypeName.
649 /// The contentTypeName is set to NULL if the branch does not
650 /// contain a collection; in that case, the type of the branch is returned.
651 /// In all other cases, NULL is returned.
652 
654  TString& contentTypeName,
655  TDictionary* &dict)
656 {
657  dict = 0;
658  contentTypeName = "";
659  if (branch->IsA() == TBranchElement::Class()) {
660  TBranchElement* brElement = (TBranchElement*)branch;
661  if (brElement->GetType() == 4
662  || brElement->GetType() == 3) {
663  TVirtualCollectionProxy* collProxy = brElement->GetCollectionProxy();
664  if (collProxy) {
665  TClass *myClass = collProxy->GetValueClass();
666  if (!myClass){
667  Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Could not get value class.");
668  return 0;
669  }
670  dict = TDictionary::GetDictionary(myClass->GetName());
671  if (!dict) dict = TDataType::GetDataType(collProxy->GetType());
672  }
673  if (!dict) {
674  // We don't know the dictionary, thus we need the content's type name.
675  // Determine it.
676  if (brElement->GetType() == 3) {
677  contentTypeName = brElement->GetClonesName();
678  dict = TDictionary::GetDictionary(brElement->GetClonesName());
679  return 0;
680  }
681  // STL:
682  TClassEdit::TSplitType splitType(brElement->GetClassName());
683  int isSTLCont = splitType.IsSTLCont();
684  if (!isSTLCont) {
685  Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Cannot determine STL collection type of %s stored in branch %s", brElement->GetClassName(), branch->GetName());
686  return brElement->GetClassName();
687  }
688  bool isMap = isSTLCont == ROOT::kSTLmap
689  || isSTLCont == ROOT::kSTLmultimap;
690  if (isMap) contentTypeName = "std::pair< ";
691  contentTypeName += splitType.fElements[1];
692  if (isMap) {
693  contentTypeName += splitType.fElements[2];
694  contentTypeName += " >";
695  }
696  return 0;
697  }
698  return 0;
699  } else if (brElement->GetType() == 31
700  || brElement->GetType() == 41) {
701  // it's a member, extract from GetClass()'s streamer info
702  TClass* clData = 0;
703  EDataType dtData = kOther_t;
704  int ExpectedTypeRet = brElement->GetExpectedType(clData, dtData);
705  if (ExpectedTypeRet == 0) {
706  dict = clData;
707  if (!dict) {
708  dict = TDataType::GetDataType(dtData);
709  }
710  if (!dict) {
711  Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s contains a data type %d for which the dictionary cannot be retrieved.",
712  branch->GetName(), (int)dtData);
713  contentTypeName = TDataType::GetTypeName(dtData);
714  return 0;
715  }
716  return 0;
717  } else if (ExpectedTypeRet == 1) {
718  int brID = brElement->GetID();
719  if (brID == -1) {
720  // top
721  Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s contains data of type %s for which the dictionary does not exist. It's needed.",
722  branch->GetName(), brElement->GetClassName());
723  contentTypeName = brElement->GetClassName();
724  return 0;
725  }
726  // Either the data type name doesn't have an EDataType entry
727  // or the streamer info doesn't have a TClass* attached.
728  TStreamerElement* element =
729  (TStreamerElement*) brElement->GetInfo()->GetElement(brID);
730  contentTypeName = element->GetTypeName();
731  return 0;
732  }
733  /* else (ExpectedTypeRet == 2)*/
734  // The streamer info entry cannot be found.
735  // TBranchElement::GetExpectedType() has already complained.
736  return "{CANNOT DETERMINE TBranchElement DATA TYPE}";
737  }
738  else if (brElement->GetType() == TBranchElement::kLeafNode){
739  TStreamerInfo *streamerInfo = brElement->GetInfo();
740  Int_t id = brElement->GetID();
741 
742  if (id >= 0){
743  TStreamerElement *element = (TStreamerElement*)streamerInfo->GetElements()->At(id);
744 
745  if (element->IsA() == TStreamerSTL::Class()){
746  TClass *myClass = brElement->GetCurrentClass();
747  if (!myClass){
748  Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get class from branch element.");
749  return 0;
750  }
751  TVirtualCollectionProxy *myCollectionProxy = myClass->GetCollectionProxy();
752  if (!myCollectionProxy){
753  Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get collection proxy from STL class");
754  return 0;
755  }
756  // Try getting the contained class
757  dict = myCollectionProxy->GetValueClass();
758  // If it fails, try to get the contained type as a primitive type
759  if (!dict) dict = TDataType::GetDataType(myCollectionProxy->GetType());
760  if (!dict){
761  Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get valueClass from collectionProxy.");
762  return 0;
763  }
764  contentTypeName = dict->GetName();
765  return 0;
766  }
767  else if (element->IsA() == TStreamerObject::Class() && !strcmp(element->GetTypeName(), "TClonesArray")){
768  if (!fProxy->Setup() || !fProxy->Read()){
769  Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Failed to get type from proxy, unable to check type");
770  contentTypeName = "UNKNOWN";
771  dict = 0;
772  return contentTypeName;
773  }
774  TClonesArray *myArray = (TClonesArray*)fProxy->GetWhere();
775  dict = myArray->GetClass();
776  contentTypeName = dict->GetName();
777  return 0;
778  }
779  else {
780  dict = brElement->GetCurrentClass();
781  if (!dict) {
782  TDictionary *myDataType = TDictionary::GetDictionary(brElement->GetTypeName());
783  dict = TDataType::GetDataType((EDataType)((TDataType*)myDataType)->GetType());
784  }
785  contentTypeName = brElement->GetTypeName();
786  return 0;
787  }
788  }
789  if (brElement->GetCurrentClass() == TClonesArray::Class()){
790  contentTypeName = "TClonesArray";
791  Warning("TTreeReaderArrayBase::GetBranchContentDataType()", "Not able to check type correctness, ignoring check");
792  dict = fDict;
793  fSetupStatus = kSetupNoCheck;
794  }
795  else if (!dict && (branch->GetSplitLevel() == 0 || brElement->GetClass()->GetCollectionProxy())){
796  // Try getting the contained class
797  dict = brElement->GetClass()->GetCollectionProxy()->GetValueClass();
798  // If it fails, try to get the contained type as a primitive type
799  if (!dict) dict = TDataType::GetDataType(brElement->GetClass()->GetCollectionProxy()->GetType());
800  if (dict) contentTypeName = dict->GetName();
801  return 0;
802  }
803  else if (!dict){
804  dict = brElement->GetClass();
805  contentTypeName = dict->GetName();
806  return 0;
807  }
808 
809  return 0;
810  }
811  return 0;
812  } else if (branch->IsA() == TBranch::Class()
813  || branch->IsA() == TBranchObject::Class()
814  || branch->IsA() == TBranchSTL::Class()) {
815  const char* dataTypeName = branch->GetClassName();
816  if ((!dataTypeName || !dataTypeName[0])
817  && branch->IsA() == TBranch::Class()) {
818  TLeaf *myLeaf = branch->GetLeaf(branch->GetName());
819  if (myLeaf){
820  TDictionary *myDataType = TDictionary::GetDictionary(myLeaf->GetTypeName());
821  if (myDataType && myDataType->IsA() == TDataType::Class()){
822  dict = TDataType::GetDataType((EDataType)((TDataType*)myDataType)->GetType());
823  contentTypeName = myLeaf->GetTypeName();
824  return 0;
825  }
826  }
827 
828  // leaflist. Can't represent.
829  Error("TTreeReaderArrayBase::GetBranchContentDataType()", "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());
830  TIter iLeaves(branch->GetListOfLeaves());
831  TLeaf* leaf = 0;
832  while ((leaf = (TLeaf*) iLeaves())) {
833  Error("TTreeReaderArrayBase::GetBranchContentDataType()", " %s.%s", branch->GetName(), leaf->GetName());
834  }
835  return 0;
836  }
837  if (dataTypeName) dict = TDictionary::GetDictionary(dataTypeName);
838  if (branch->IsA() == TBranchSTL::Class()){
839  Warning("TTreeReaderArrayBase::GetBranchContentDataType()", "Not able to check type correctness, ignoring check");
840  dict = fDict;
841  fSetupStatus = kSetupNoCheck;
842  return 0;
843  }
844  return dataTypeName;
845  } else if (branch->IsA() == TBranchClones::Class()) {
846  dict = TClonesArray::Class();
847  return "TClonesArray";
848  } else if (branch->IsA() == TBranchRef::Class()) {
849  // Can't represent.
850  Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s is a TBranchRef and cannot be represented as a C++ type.", branch->GetName());
851  return 0;
852  } else {
853  Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s is of type %s - something that is not handled yet.", branch->GetName(), branch->IsA()->GetName());
854  return 0;
855  }
856 
857  return 0;
858 }
Describe Streamer information for one class version.
Definition: TStreamerInfo.h:43
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
Definition: TBranch.cxx:1256
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
#define ARGS(alist)
Definition: gifencode.c:10
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
Definition: TDataType.cxx:440
TVirtualCollectionProxy * GetCollectionProxy()
Return the collection proxy describing the branch content, if any.
const char * GetBranchContentDataType(TBranch *branch, TString &contentTypeName, TDictionary *&dict)
Access a branch&#39;s collection content (not the collection itself) through a proxy. ...
TString GetTypeName()
Get basic type of typedef, e,g.
Definition: TDataType.cxx:149
Int_t GetSplitLevel() const
Definition: TBranch.h:186
Int_t GetType() const
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
TTreeReader is a simple, robust and fast interface to read values from a TTree, TChain or TNtuple...
Definition: TTreeReader.h:43
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
virtual TClass * GetValueClass() const =0
const char * Size
Definition: TXMLSetup.cxx:56
TStreamerElement * GetElement(Int_t id) const
virtual const char * GetTypeName() const
Definition: TLeaf.h:76
virtual TLeaf * GetLeafCounter(Int_t &countval) const
Return a pointer to the counter of this leaf.
Definition: TLeaf.cxx:168
Regular expression class.
Definition: TRegexp.h:31
static TDictionary * GetDictionary(const char *name)
Definition: TDictionary.cxx:84
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
virtual void * GetStart(UInt_t=0)
Definition: TBranchProxy.h:197
Int_t GetArrayLength() const
EReadStatus ProxyRead()
Try to read the value from the TBranchProxy, returns the status of the read.
int Int_t
Definition: RtypesCore.h:41
Type GetType(const std::string &Name)
Definition: Systematics.cxx:34
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
virtual EDataType GetType() const =0
void SetContentDict(TDictionary *dict)
TBranchElement * GetBranchCount() const
TTree * GetTree() const
Definition: TTreeReader.h:152
const Detail::TBranchProxy * GetProxy() const
void Class()
Definition: Class.C:29
unsigned char Byte_t
Definition: RtypesCore.h:60
virtual TLeaf * GetLeaf(const char *name) const
Return pointer to the 1st Leaf named name in thisBranch.
Definition: TBranch.cxx:1552
Int_t GetID() const
virtual Int_t GetLenType() const
Definition: TLeaf.h:70
TDictionary * GetContentDict() const
virtual const char * GetClonesName() const
TTreeReaderValueBase::EReadStatus fReadStatus
bool GetBranchAndLeaf(TBranch *&branch, TLeaf *&myLeaf, TDictionary *&branchActualType)
Determine the branch / leaf and its type; reset fProxy / fSetupStatus on error.
virtual Int_t GetLen() const
Return the number of effective elements of this leaf.
Definition: TLeaf.cxx:279
virtual const char * GetTypeName() const
Return type name of element in the branch.
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:158
virtual Bool_t HasPointers() const =0
virtual TLeaf * GetLeafCount() const
Definition: TLeaf.h:66
TClass * GetCurrentClass()
Return a pointer to the current type of the data member corresponding to branch element.
void * GetAddress()
Returns the memory address of the object being read.
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:71
void Warning(const char *location, const char *msgfmt,...)
A Branch for the case of an object.
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
#define ClassImp(name)
Definition: Rtypes.h:336
TVirtualCollectionProxy * GetCollection()
Definition: TBranchProxy.h:194
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
EDataType
Definition: TDataType.h:28
virtual void * At(UInt_t idx)=0
TObjArray * GetListOfLeaves()
Definition: TBranch.h:183
TClass * GetClass() const
Definition: TClonesArray.h:57
TLeaf * GetLeaf()
If we are reading a leaf, return the corresponding TLeaf.
Int_t GetClassSize() const
Definition: TClass.h:373
TObjArray * GetElements() const
virtual UInt_t Size() const =0
typedef void((*Func_t)())
An array of clone (identical) objects.
Definition: TClonesArray.h:32
const char * GetTypeName() const
virtual TClass * GetClass() const
TTree * GetTree() const
Definition: TBranch.h:188
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
virtual void * At(Detail::TBranchProxy *, size_t)=0
Base class for all the proxy object.
Definition: TBranchProxy.h:65
TBranch * GetBranch() const
Definition: TLeaf.h:65
A TTree is a list of TBranches.
Definition: TBranch.h:57
Int_t GetOffset() const
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1625
void Error(ErrorHandler_t func, int code, const char *va_(fmt),...)
Write error message and call a handler, if required.
TClass * GetClass() const
void SetImpl(TBranch *branch, TLeaf *myLeaf)
Create the TVirtualCollectionReader object for our branch.
virtual size_t GetSize(Detail::TBranchProxy *)=0