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