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 TDynamicArrayReader : public BASE {
201
202 // TVirtualSizeReaderImpl and TSizeReaderImpl type-erase the reading of the size leaf.
203 class TVirtualSizeReaderImpl {
204 public:
205 virtual ~TVirtualSizeReaderImpl() = default;
206 virtual size_t GetSize() = 0;
207 };
208
209 template <typename T>
210 class TSizeReaderImpl final : public TVirtualSizeReaderImpl {
211 TTreeReaderValue<T> fSizeReader;
212
213 public:
214 TSizeReaderImpl(TTreeReader &r, const char *leafName) : fSizeReader(r, leafName) {}
215 size_t GetSize() final { return *fSizeReader; }
216 };
217
218 std::unique_ptr<TVirtualSizeReaderImpl> fSizeReader;
219
220 public:
221 template <class... ARGS>
222 TDynamicArrayReader(TTreeReader *treeReader, const char *leafName, ARGS &&...args)
223 : BASE(std::forward<ARGS>(args)...)
224 {
225 std::string foundLeafName = leafName;
226 TLeaf* sizeLeaf = treeReader->GetTree()->FindLeaf(foundLeafName.c_str());
227
228 if (!sizeLeaf) {
229 // leafName might be "top.currentParent.N". But "N" might really be "top.N"!
230 // Strip parents until we find the leaf.
231 std::string leafNameNoParent = leafName;
232 std::string parent;
233 auto posLastDot = leafNameNoParent.rfind('.');
234 if (posLastDot != leafNameNoParent.npos) {
235 parent = leafNameNoParent.substr(0, posLastDot);
236 leafNameNoParent.erase(0, posLastDot + 1);
237 }
238
239 do {
240 if (!sizeLeaf && !parent.empty()) {
241 auto posLastDotParent = parent.rfind('.');
242 if (posLastDotParent != parent.npos)
243 parent = parent.substr(0, posLastDot);
244 else
245 parent.clear();
246 }
247
248 foundLeafName = parent;
249 if (!parent.empty())
250 foundLeafName += ".";
251 foundLeafName += leafNameNoParent;
252 sizeLeaf = treeReader->GetTree()->FindLeaf(foundLeafName.c_str());
253 } while (!sizeLeaf && !parent.empty());
254 }
255
256 if (!sizeLeaf) {
257 Error("TDynamicArrayReader ", "Cannot find leaf count for %s or any parent branch!", leafName);
258 return;
259 }
260
261 const std::string leafType = sizeLeaf->GetTypeName();
262 if (leafType == "Int_t") {
263 fSizeReader.reset(new TSizeReaderImpl<Int_t>(*treeReader, foundLeafName.c_str()));
264 } else if (leafType == "UInt_t") {
265 fSizeReader.reset(new TSizeReaderImpl<UInt_t>(*treeReader, foundLeafName.c_str()));
266 } else if (leafType == "Short_t") {
267 fSizeReader.reset(new TSizeReaderImpl<Short_t>(*treeReader, foundLeafName.c_str()));
268 } else if (leafType == "UShort_t") {
269 fSizeReader.reset(new TSizeReaderImpl<UShort_t>(*treeReader, foundLeafName.c_str()));
270 } else if (leafType == "Long_t") {
271 fSizeReader.reset(new TSizeReaderImpl<Long_t>(*treeReader, foundLeafName.c_str()));
272 } else if (leafType == "ULong_t") {
273 fSizeReader.reset(new TSizeReaderImpl<ULong_t>(*treeReader, foundLeafName.c_str()));
274 } else if (leafType == "Long64_t") {
275 fSizeReader.reset(new TSizeReaderImpl<Long64_t>(*treeReader, foundLeafName.c_str()));
276 } else if (leafType == "ULong64_t") {
277 fSizeReader.reset(new TSizeReaderImpl<ULong64_t>(*treeReader, foundLeafName.c_str()));
278 } else {
279 Error("TDynamicArrayReader ",
280 "Unsupported size type for leaf %s. Supported types are int, short int, long int, long long int and "
281 "their unsigned counterparts.",
282 leafName);
283 }
284 }
285
286 size_t GetSize(ROOT::Detail::TBranchProxy * /*proxy*/) override { return fSizeReader->GetSize(); }
287 };
288
289 class TArrayParameterSizeReader : public TDynamicArrayReader<TObjectArrayReader> {
290 public:
291 TArrayParameterSizeReader(TTreeReader *treeReader, const char *branchName)
292 : TDynamicArrayReader<TObjectArrayReader>(treeReader, branchName)
293 {
294 }
295 };
296
297 // Reader interface for fixed size arrays
298 class TArrayFixedSizeReader : public TObjectArrayReader {
299 private:
300 Int_t fSize;
301
302 public:
303 TArrayFixedSizeReader(Int_t sizeArg) : fSize(sizeArg) {}
304
305 virtual size_t GetSize(ROOT::Detail::TBranchProxy* /*proxy*/) { return fSize; }
306 };
307
308 class TBasicTypeArrayReader final: public TVirtualCollectionReader {
309 public:
310 ~TBasicTypeArrayReader() {}
311
313 if (!proxy->Read()){
315 Error("TBasicTypeArrayReader::GetCP()", "Read error in TBranchProxy.");
316 return 0;
317 }
319 return (TVirtualCollectionProxy*) proxy->GetCollection();
320 }
321
322 virtual size_t GetSize(ROOT::Detail::TBranchProxy* proxy){
323 TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
324 if (!myCollectionProxy) return 0;
325 return myCollectionProxy->Size();
326 }
327
328 virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx){
329 TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
330 if (!myCollectionProxy) return 0;
331 return (Byte_t*)myCollectionProxy->At(idx) + proxy->GetOffset();
332 }
333 };
334
335 class TBasicTypeClonesReader final: public TClonesReader {
336 private:
337 Int_t fOffset;
338 public:
339 TBasicTypeClonesReader(Int_t offsetArg) : fOffset(offsetArg) {}
340
341 virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx){
342 TClonesArray *myClonesArray = GetCA(proxy);
343 if (!myClonesArray) return 0;
344 return (Byte_t*)myClonesArray->At(idx) + fOffset;
345 }
346 };
347
348 class TLeafReader : public TVirtualCollectionReader {
349 private:
350 TTreeReaderValueBase *fValueReader;
351 Int_t fElementSize;
352 public:
353 TLeafReader(TTreeReaderValueBase *valueReaderArg) : fValueReader(valueReaderArg), fElementSize(-1) {}
354
355 virtual size_t GetSize(ROOT::Detail::TBranchProxy* /*proxy*/){
356 TLeaf *myLeaf = fValueReader->GetLeaf();
357 return myLeaf ? myLeaf->GetLen() : 0; // Error will be printed by GetLeaf
358 }
359
360 virtual void* At(ROOT::Detail::TBranchProxy* /*proxy*/, size_t idx){
361 ProxyRead();
362 void *address = fValueReader->GetAddress();
363 if (fElementSize == -1){
364 TLeaf *myLeaf = fValueReader->GetLeaf();
365 if (!myLeaf) return 0; // Error will be printed by GetLeaf
366 fElementSize = myLeaf->GetLenType();
367 }
368 return (Byte_t*)address + (fElementSize * idx);
369 }
370
371 protected:
372 void ProxyRead(){
373 fValueReader->ProxyRead();
374 }
375 };
376
377 class TLeafParameterSizeReader : public TDynamicArrayReader<TLeafReader> {
378 public:
379 TLeafParameterSizeReader(TTreeReader *treeReader, const char *leafName, TTreeReaderValueBase *valueReaderArg)
380 : TDynamicArrayReader<TLeafReader>(treeReader, leafName, valueReaderArg)
381 {
382 }
383
384 size_t GetSize(ROOT::Detail::TBranchProxy* proxy) override {
385 ProxyRead();
386 return TDynamicArrayReader<TLeafReader>::GetSize(proxy);
387 }
388 };
389}
390
391
392
394
395////////////////////////////////////////////////////////////////////////////////
396/// Create the proxy object for our branch.
397
399{
400 if (fProxy) {
401 return;
402 }
403
404 fSetupStatus = kSetupInternalError; // Fallback; set to something concrete below.
405 if (!fTreeReader) {
406 Error("TTreeReaderArrayBase::CreateProxy()", "TTreeReader object not set / available for branch %s!",
407 fBranchName.Data());
408 fSetupStatus = kSetupTreeDestructed;
409 return;
410 }
411 if (!fDict) {
412 TBranch* br = fTreeReader->GetTree()->GetBranch(fBranchName);
413 const char* brDataType = "{UNDETERMINED}";
414 if (br) {
415 TDictionary* dictUnused = 0;
416 brDataType = GetBranchDataType(br, dictUnused, fDict);
417 }
418 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.",
419 GetDerivedTypeName(), fBranchName.Data(), brDataType);
420 fSetupStatus = kSetupMissingDictionary;
421 return;
422 }
423
424 // Access a branch's collection content (not the collection itself)
425 // through a proxy.
426 // Search for the branchname, determine what it contains, and wire the
427 // TBranchProxy representing it to us so we can access its data.
428
429 TDictionary* branchActualType = 0;
430 TBranch* branch = nullptr;
431 TLeaf *myLeaf = nullptr;
432 if (!GetBranchAndLeaf(branch, myLeaf, branchActualType))
433 return;
434
435 if (!fDict) {
436 Error("TTreeReaderArrayBase::CreateProxy()",
437 "No dictionary for branch %s.", fBranchName.Data());
438 return;
439 }
440
441 TNamedBranchProxy* namedProxy = fTreeReader->FindProxy(fBranchName);
442 if (namedProxy) {
443 if (namedProxy->GetContentDict() == fDict) {
444 fSetupStatus = kSetupMatch;
445 fProxy = namedProxy->GetProxy();
446 SetImpl(branch, myLeaf);
447 return;
448 }
449
450 // Update named proxy's dictionary
451 if (!namedProxy->GetContentDict()) {
452 namedProxy->SetContentDict(fDict);
453 fProxy = namedProxy->GetProxy();
454 if (fProxy)
455 fSetupStatus = kSetupMatch;
456 } else {
457 Error("TTreeReaderArrayBase::CreateProxy()",
458 "Type ambiguity (want %s, have %s) for branch %s.",
459 fDict->GetName(), namedProxy->GetContentDict()->GetName(), fBranchName.Data());
460 }
461 }
462 else {
463 TString membername;
464
465 bool isTopLevel = branch->GetMother() == branch;
466 if (!isTopLevel) {
467 membername = strrchr(branch->GetName(), '.');
468 if (membername.IsNull()) {
469 membername = branch->GetName();
470 }
471 }
472 auto director = fTreeReader->fDirector;
473 // Determine if the branch is actually in a Friend TTree and if so which.
474 if (branch->GetTree() != fTreeReader->GetTree()->GetTree()) {
475 // It is in a friend, let's find the 'index' in the list of friend ...
476 int index = -1;
477 int current = 0;
478 for(auto fe : TRangeDynCast<TFriendElement>( fTreeReader->GetTree()->GetTree()->GetListOfFriends())) {
479 if (branch->GetTree() == fe->GetTree()) {
480 index = current;
481 }
482 ++current;
483 }
484 if (index == -1) {
485 Error("TTreeReaderArrayBase::CreateProxy()", "The branch %s is contained in a Friend TTree that is not directly attached to the main.\n"
486 "This is not yet supported by TTreeReader.",
487 fBranchName.Data());
488 return;
489 }
490 TFriendProxy *feproxy = nullptr;
491 if ((size_t)index < fTreeReader->fFriendProxies.size()) {
492 feproxy = fTreeReader->fFriendProxies.at(index);
493 }
494 if (!feproxy) {
495 feproxy = new ROOT::Internal::TFriendProxy(director, fTreeReader->GetTree(), index);
496 fTreeReader->fFriendProxies.resize(index+1);
497 fTreeReader->fFriendProxies.at(index) = feproxy;
498 }
499 director = feproxy->GetDirector();
500 }
501 namedProxy = new TNamedBranchProxy(director, branch, fBranchName, membername);
502 fTreeReader->AddProxy(namedProxy);
503 fProxy = namedProxy->GetProxy();
504 if (fProxy)
505 fSetupStatus = kSetupMatch;
506 else
507 fSetupStatus = kSetupMismatch;
508 }
509
510 if (!myLeaf){
511 TString branchActualTypeName;
512 const char* nonCollTypeName = GetBranchContentDataType(branch, branchActualTypeName, branchActualType);
513 if (nonCollTypeName) {
514 Error("TTreeReaderArrayBase::CreateContentProxy()", "The branch %s contains data of type %s, which should be accessed through a TTreeReaderValue< %s >.",
515 fBranchName.Data(), nonCollTypeName, nonCollTypeName);
516 if (fSetupStatus == kSetupInternalError)
517 fSetupStatus = kSetupNotACollection;
518 fProxy = 0;
519 return;
520 }
521 if (!branchActualType) {
522 if (branchActualTypeName.IsNull()) {
523 Error("TTreeReaderArrayBase::CreateContentProxy()", "Cannot determine the type contained in the collection of branch %s. That's weird - please report!",
524 fBranchName.Data());
525 } else {
526 Error("TTreeReaderArrayBase::CreateContentProxy()", "The branch %s contains data of type %s, which does not have a dictionary.",
527 fBranchName.Data(), branchActualTypeName.Data());
528 if (fSetupStatus == kSetupInternalError)
529 fSetupStatus = kSetupMissingDictionary;
530 }
531 fProxy = 0;
532 return;
533 }
534
535 if (fDict != branchActualType) {
536 Error("TTreeReaderArrayBase::CreateContentProxy()", "The branch %s contains data of type %s. It cannot be accessed by a TTreeReaderArray<%s>",
537 fBranchName.Data(), branchActualType->GetName(), fDict->GetName());
538 if (fSetupStatus == kSetupInternalError || fSetupStatus >= 0)
539 fSetupStatus = kSetupMismatch;
540
541 // Update named proxy's dictionary
542 if (!namedProxy->GetContentDict()) {
543 namedProxy->SetContentDict(fDict);
544 }
545
546 // fProxy = 0;
547 // return;
548 }
549 }
550
551 SetImpl(branch, myLeaf);
552}
553
554////////////////////////////////////////////////////////////////////////////////
555/// Determine the branch / leaf and its type; reset fProxy / fSetupStatus on error.
556
558 TDictionary* &branchActualType) {
559 myLeaf = nullptr;
560 branch = fTreeReader->GetTree()->GetBranch(fBranchName);
561 if (branch)
562 return true;
563
564 if (!fBranchName.Contains(".")) {
565 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.", fBranchName.Data());
566 fSetupStatus = kSetupMissingBranch;
567 fProxy = 0;
568 return false;
569 }
570
571 TRegexp leafNameExpression ("\\.[a-zA-Z0-9_]+$");
572 TString leafName (fBranchName(leafNameExpression));
573 TString branchName = fBranchName(0, fBranchName.Length() - leafName.Length());
574 branch = fTreeReader->GetTree()->GetBranch(branchName);
575 if (!branch){
576 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.", fBranchName.Data());
577 fSetupStatus = kSetupMissingBranch;
578 fProxy = 0;
579 return false;
580 }
581
582 myLeaf = branch->GetLeaf(TString(leafName(1, leafName.Length())));
583 if (!myLeaf){
584 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());
585 fSetupStatus = kSetupMissingBranch;
586 fProxy = 0;
587 return false;
588 }
589
591 if (!tempDict){
592 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Failed to get the dictionary for %s.", myLeaf->GetTypeName());
593 fSetupStatus = kSetupMissingDictionary;
594 fProxy = 0;
595 return false;
596 }
597
598 if (tempDict->IsA() == TDataType::Class() && TDictionary::GetDictionary(((TDataType*)tempDict)->GetTypeName()) == fDict){
599 //fLeafOffset = myLeaf->GetOffset() / 4;
600 branchActualType = fDict;
601 fLeaf = myLeaf;
602 fBranchName = branchName;
603 fLeafName = leafName(1, leafName.Length());
604 fHaveLeaf = (fLeafName.Length() > 0);
605 fSetupStatus = kSetupMatchLeaf;
606 }
607 else {
608 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Leaf of type %s cannot be read by TTreeReaderValue<%s>.", myLeaf->GetTypeName(), fDict->GetName());
609 fProxy = 0;
610 fSetupStatus = kSetupMismatch;
611 return false;
612 }
613 return true;
614}
615
616
617
618
619////////////////////////////////////////////////////////////////////////////////
620/// Create the TVirtualCollectionReader object for our branch.
621
623{
624 if (fImpl)
625 return;
626
627 // Access a branch's collection content (not the collection itself)
628 // through a proxy.
629 // Search for the branchname, determine what it contains, and wire the
630 // TBranchProxy representing it to us so we can access its data.
631 // A proxy for branch must not have been created before (i.e. check
632 // fProxies before calling this function!)
633
634 if (myLeaf){
635 if (!myLeaf->GetLeafCount()){
636 fImpl = std::make_unique<TLeafReader>(this);
637 }
638 else {
639 TString leafFullName = myLeaf->GetBranch()->GetName();
640 leafFullName += ".";
641 leafFullName += myLeaf->GetLeafCount()->GetName();
642 fImpl = std::make_unique<TLeafParameterSizeReader>(fTreeReader, leafFullName.Data(), this);
643 }
644 fSetupStatus = kSetupMatchLeaf;
645 }
646 else if (branch->IsA() == TBranchElement::Class()) {
647 TBranchElement* branchElement = ((TBranchElement*)branch);
648
649 TStreamerInfo *streamerInfo = branchElement->GetInfo();
650 Int_t id = branchElement->GetID();
651
652 if (id >= 0){ // Not root node?
653 // Int_t offset = streamerInfo->GetOffsets()[id];
654 TStreamerElement *element = (TStreamerElement*)streamerInfo->GetElements()->At(id);
655 // Bool_t isPointer = element->IsaPointer();
656 // TClass *classPointer = element->GetClassPointer();
657
658 if (fSetupStatus == kSetupInternalError)
659 fSetupStatus = kSetupMatch;
660 if (element->IsA() == TStreamerSTL::Class()){
661 fImpl = std::make_unique<TSTLReader>();
662 }
663 else if (element->IsA() == TStreamerObject::Class()){
664 //fImpl = new TObjectArrayReader(); // BArray[12]
665
666 if (element->GetClass() == TClonesArray::Class()){
667 fImpl = std::make_unique<TClonesReader>();
668 }
669 else if (branchElement->GetType() == TBranchElement::kSTLMemberNode){
670 fImpl = std::make_unique<TBasicTypeArrayReader>();
671 }
672 else if (branchElement->GetType() == TBranchElement::kClonesMemberNode){
673 // TBasicTypeClonesReader should work for object
674 fImpl = std::make_unique<TBasicTypeClonesReader>(element->GetOffset());
675 }
676 else {
677 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
678 }
679 }
680 else if (element->IsA() == TStreamerLoop::Class()) {
681 fImpl = std::make_unique<TArrayParameterSizeReader>(fTreeReader, branchElement->GetBranchCount()->GetName());
682 }
683 else if (element->IsA() == TStreamerBasicType::Class()){
684 if (branchElement->GetType() == TBranchElement::kSTLMemberNode){
685 fImpl = std::make_unique<TBasicTypeArrayReader>();
686 }
687 else if (branchElement->GetType() == TBranchElement::kClonesMemberNode){
688 fImpl = std::make_unique<TBasicTypeClonesReader>(element->GetOffset());
689 }
690 else {
691 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
692 ((TObjectArrayReader*)fImpl.get())->SetBasicTypeSize(((TDataType*)fDict)->Size());
693 }
694 }
695 else if (element->IsA() == TStreamerBasicPointer::Class()) {
696 fImpl = std::make_unique<TArrayParameterSizeReader>(fTreeReader, branchElement->GetBranchCount()->GetName());
697 ((TArrayParameterSizeReader*)fImpl.get())->SetBasicTypeSize(((TDataType*)fDict)->Size());
698 }
699 else if (element->IsA() == TStreamerBase::Class()){
700 fImpl = std::make_unique<TClonesReader>();
701 } else {
702 Error("TTreeReaderArrayBase::SetImpl()",
703 "Cannot read branch %s: unhandled streamer element type %s",
704 fBranchName.Data(), element->IsA()->GetName());
705 fSetupStatus = kSetupInternalError;
706 }
707 }
708 else { // We are at root node?
709 if (branchElement->GetClass()->GetCollectionProxy()){
710 fImpl = std::make_unique<TCollectionLessSTLReader>(branchElement->GetClass()->GetCollectionProxy());
711 }
712 }
713 } else if (branch->IsA() == TBranch::Class()) {
714 auto topLeaf = branch->GetLeaf(branch->GetName());
715 if (!topLeaf) {
716 Error("TTreeReaderArrayBase::SetImpl", "Failed to get the top leaf from the branch");
717 fSetupStatus = kSetupMissingBranch;
718 return;
719 }
720 // We could have used GetLeafCounter, but it does not work well with Double32_t and Float16_t: ROOT-10149
721 auto sizeLeaf = topLeaf->GetLeafCount();
722 if (fSetupStatus == kSetupInternalError)
723 fSetupStatus = kSetupMatch;
724 if (!sizeLeaf) {
725 fImpl = std::make_unique<TArrayFixedSizeReader>(topLeaf->GetLenStatic());
726 }
727 else {
728 fImpl = std::make_unique<TArrayParameterSizeReader>(fTreeReader, sizeLeaf->GetName());
729 }
730 ((TObjectArrayReader*)fImpl.get())->SetBasicTypeSize(((TDataType*)fDict)->Size());
731 } else if (branch->IsA() == TBranchClones::Class()) {
732 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchClones not implemented");
733 fSetupStatus = kSetupInternalError;
734 } else if (branch->IsA() == TBranchObject::Class()) {
735 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchObject not implemented");
736 fSetupStatus = kSetupInternalError;
737 } else if (branch->IsA() == TBranchSTL::Class()) {
738 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchSTL not implemented");
739 fImpl = std::make_unique<TSTLReader>();
740 fSetupStatus = kSetupInternalError;
741 } else if (branch->IsA() == TBranchRef::Class()) {
742 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchRef not implemented");
743 fSetupStatus = kSetupInternalError;
744 }
745}
746
747////////////////////////////////////////////////////////////////////////////////
748/// Access a branch's collection content (not the collection itself)
749/// through a proxy.
750/// Retrieve the type of data contained in the collection stored by branch;
751/// put its dictionary into dict, If there is no dictionary, put its type
752/// name into contentTypeName.
753/// The contentTypeName is set to NULL if the branch does not
754/// contain a collection; in that case, the type of the branch is returned.
755/// In all other cases, NULL is returned.
756
758 TString& contentTypeName,
759 TDictionary* &dict)
760{
761 dict = nullptr;
762 contentTypeName = "";
763 if (branch->IsA() == TBranchElement::Class()) {
764 TBranchElement* brElement = (TBranchElement*)branch;
765 if (brElement->GetType() == 4
766 || brElement->GetType() == 3) {
767 TVirtualCollectionProxy* collProxy = brElement->GetCollectionProxy();
768 if (collProxy) {
769 TClass *myClass = collProxy->GetValueClass();
770 if (!myClass){
771 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Could not get value class.");
772 return 0;
773 }
774 dict = TDictionary::GetDictionary(myClass->GetName());
775 if (!dict) dict = TDataType::GetDataType(collProxy->GetType());
776 }
777 if (!dict) {
778 // We don't know the dictionary, thus we need the content's type name.
779 // Determine it.
780 if (brElement->GetType() == 3) {
781 contentTypeName = brElement->GetClonesName();
782 dict = TDictionary::GetDictionary(brElement->GetClonesName());
783 return 0;
784 }
785 // STL:
786 TClassEdit::TSplitType splitType(brElement->GetClassName());
787 int isSTLCont = splitType.IsSTLCont();
788 if (!isSTLCont) {
789 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Cannot determine STL collection type of %s stored in branch %s", brElement->GetClassName(), branch->GetName());
790 return brElement->GetClassName();
791 }
792 bool isMap = isSTLCont == ROOT::kSTLmap
793 || isSTLCont == ROOT::kSTLmultimap;
794 if (isMap) contentTypeName = "std::pair< ";
795 contentTypeName += splitType.fElements[1];
796 if (isMap) {
797 contentTypeName += splitType.fElements[2];
798 contentTypeName += " >";
799 }
800 return 0;
801 }
802 return 0;
803 } else if (brElement->GetType() == 31
804 || brElement->GetType() == 41) {
805 // it's a member, extract from GetClass()'s streamer info
806 TClass* clData = 0;
807 EDataType dtData = kOther_t;
808 int ExpectedTypeRet = brElement->GetExpectedType(clData, dtData);
809 if (ExpectedTypeRet == 0) {
810 dict = clData;
811 if (!dict) {
812 dict = TDataType::GetDataType(dtData);
813 }
814 if (!dict) {
815 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s contains a data type %d for which the dictionary cannot be retrieved.",
816 branch->GetName(), (int)dtData);
817 contentTypeName = TDataType::GetTypeName(dtData);
818 return 0;
819 }
820 return 0;
821 } else if (ExpectedTypeRet == 1) {
822 int brID = brElement->GetID();
823 if (brID == -1) {
824 // top
825 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s contains data of type %s for which the dictionary does not exist. It's needed.",
826 branch->GetName(), brElement->GetClassName());
827 contentTypeName = brElement->GetClassName();
828 return 0;
829 }
830 // Either the data type name doesn't have an EDataType entry
831 // or the streamer info doesn't have a TClass* attached.
832 TStreamerElement* element =
833 (TStreamerElement*) brElement->GetInfo()->GetElement(brID);
834 contentTypeName = element->GetTypeName();
835 return 0;
836 }
837 /* else (ExpectedTypeRet == 2)*/
838 // The streamer info entry cannot be found.
839 // TBranchElement::GetExpectedType() has already complained.
840 return "{CANNOT DETERMINE TBranchElement DATA TYPE}";
841 }
842 else if (brElement->GetType() == TBranchElement::kLeafNode){
843 TStreamerInfo *streamerInfo = brElement->GetInfo();
844 Int_t id = brElement->GetID();
845
846 if (id >= 0){
847 TStreamerElement *element = (TStreamerElement*)streamerInfo->GetElements()->At(id);
848
849 if (element->IsA() == TStreamerSTL::Class()){
850 TClass *myClass = brElement->GetCurrentClass();
851 if (!myClass){
852 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get class from branch element.");
853 return 0;
854 }
855 TVirtualCollectionProxy *myCollectionProxy = myClass->GetCollectionProxy();
856 if (!myCollectionProxy){
857 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get collection proxy from STL class");
858 return 0;
859 }
860 // Try getting the contained class
861 dict = myCollectionProxy->GetValueClass();
862 // If it fails, try to get the contained type as a primitive type
863 if (!dict) dict = TDataType::GetDataType(myCollectionProxy->GetType());
864 if (!dict){
865 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get valueClass from collectionProxy.");
866 return 0;
867 }
868 contentTypeName = dict->GetName();
869 return 0;
870 }
871 else if (element->IsA() == TStreamerObject::Class() && !strcmp(element->GetTypeName(), "TClonesArray")){
872 if (!fProxy->Setup() || !fProxy->Read()){
873 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Failed to get type from proxy, unable to check type");
874 contentTypeName = "UNKNOWN";
875 dict = 0;
876 return contentTypeName;
877 }
878 TClonesArray *myArray = (TClonesArray*)fProxy->GetWhere();
879 dict = myArray->GetClass();
880 contentTypeName = dict->GetName();
881 return 0;
882 }
883 else {
884 dict = brElement->GetCurrentClass();
885 if (!dict) {
886 TDictionary *myDataType = TDictionary::GetDictionary(brElement->GetTypeName());
887 dict = TDataType::GetDataType((EDataType)((TDataType*)myDataType)->GetType());
888 }
889 contentTypeName = brElement->GetTypeName();
890 return 0;
891 }
892 }
893 if (brElement->GetCurrentClass() == TClonesArray::Class()){
894 contentTypeName = "TClonesArray";
895 Warning("TTreeReaderArrayBase::GetBranchContentDataType()", "Not able to check type correctness, ignoring check");
896 dict = fDict;
897 fSetupStatus = kSetupNoCheck;
898 }
899 else if (!dict && (branch->GetSplitLevel() == 0 || brElement->GetClass()->GetCollectionProxy())){
900 // Try getting the contained class
901 dict = brElement->GetClass()->GetCollectionProxy()->GetValueClass();
902 // If it fails, try to get the contained type as a primitive type
903 if (!dict) dict = TDataType::GetDataType(brElement->GetClass()->GetCollectionProxy()->GetType());
904 if (dict) contentTypeName = dict->GetName();
905 return 0;
906 }
907 else if (!dict){
908 dict = brElement->GetClass();
909 contentTypeName = dict->GetName();
910 return 0;
911 }
912
913 return 0;
914 }
915 return 0;
916 } else if (branch->IsA() == TBranch::Class()
917 || branch->IsA() == TBranchObject::Class()
918 || branch->IsA() == TBranchSTL::Class()) {
919 const char* dataTypeName = branch->GetClassName();
920 if ((!dataTypeName || !dataTypeName[0])
921 && branch->IsA() == TBranch::Class()) {
922 auto myLeaf = branch->GetLeaf(branch->GetName());
923 if (myLeaf){
924 auto myDataType = TDictionary::GetDictionary(myLeaf->GetTypeName());
925 if (myDataType && myDataType->IsA() == TDataType::Class()){
926 auto typeEnumConstant = EDataType(((TDataType*)myDataType)->GetType());
927 // We need to consider Double32_t and Float16_t as dounle and float respectively
928 // since this is the type the user uses to instantiate the TTreeReaderArray template.
929 if (typeEnumConstant == kDouble32_t) typeEnumConstant = kDouble_t;
930 else if (typeEnumConstant == kFloat16_t) typeEnumConstant = kFloat_t;
931 dict = TDataType::GetDataType(typeEnumConstant);
932 contentTypeName = myLeaf->GetTypeName();
933 return 0;
934 }
935 }
936
937 // leaflist. Can't represent.
938 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());
939 TIter iLeaves(branch->GetListOfLeaves());
940 TLeaf* leaf = 0;
941 while ((leaf = (TLeaf*) iLeaves())) {
942 Error("TTreeReaderArrayBase::GetBranchContentDataType()", " %s.%s", branch->GetName(), leaf->GetName());
943 }
944 return 0;
945 }
946 if (dataTypeName) dict = TDictionary::GetDictionary(dataTypeName);
947 if (branch->IsA() == TBranchSTL::Class()){
948 Warning("TTreeReaderArrayBase::GetBranchContentDataType()", "Not able to check type correctness, ignoring check");
949 dict = fDict;
950 fSetupStatus = kSetupNoCheck;
951 return 0;
952 }
953 return dataTypeName;
954 } else if (branch->IsA() == TBranchClones::Class()) {
955 dict = TClonesArray::Class();
956 return "TClonesArray";
957 } else if (branch->IsA() == TBranchRef::Class()) {
958 // Can't represent.
959 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s is a TBranchRef and cannot be represented as a C++ type.", branch->GetName());
960 return 0;
961 } else {
962 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s is of type %s - something that is not handled yet.", branch->GetName(), branch->IsA()->GetName());
963 return 0;
964 }
965
966 return 0;
967}
size_t fSize
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
unsigned char Byte_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:375
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
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Base class for all the proxy object.
Definition: TBranchProxy.h:74
virtual void * GetStart(UInt_t=0)
Definition: TBranchProxy.h:413
TVirtualCollectionProxy * GetCollection()
Definition: TBranchProxy.h:410
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.
static TClass * Class()
A Branch for the case of an object.
TBranchElement * GetBranchCount() const
static TClass * Class()
Int_t GetID() const
const char * GetClassName() const override
Return the name of the user class whose content is stored in this branch, if any.
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
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
Int_t GetExpectedType(TClass *&clptr, EDataType &type) override
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
static TClass * Class()
static TClass * Class()
static TClass * Class()
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
static TClass * Class()
Int_t GetSplitLevel() const
Definition: TBranch.h:246
TClass * IsA() const override
Definition: TBranch.h:291
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:2897
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
static TClass * Class()
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
static TClass * Class()
TString GetTypeName()
Get basic type of typedef, e,g.: "class TDirectory*" -> "TDirectory".
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
TClass * IsA() const override
Definition: TDictionary.h:224
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
const char * GetName() const override
Returns name of object.
Definition: TNamed.h:47
Int_t GetEntries() const override
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:523
TObject * At(Int_t idx) const override
Definition: TObjArray.h:164
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:84
Regular expression class.
Definition: TRegexp.h:31
static TClass * Class()
static TClass * Class()
static TClass * Class()
Int_t GetArrayLength() const
const char * GetTypeName() const
TClass * GetClass() const
TClass * IsA() const override
Int_t GetOffset() const
Describes a persistent version of a class.
Definition: TStreamerInfo.h:39
TStreamerElement * GetElement(Int_t id) const override
TObjArray * GetElements() const override
static TClass * Class()
static TClass * Class()
static TClass * Class()
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:181
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:5256
virtual TTree * GetTree() const
Definition: TTree.h:513
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition: TTree.cxx:4881
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:206
std::vector< std::string > fElements
Definition: TClassEdit.h:141
#define ARGS(alist)
Definition: gifencode.c:10