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