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