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