Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
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 "TEnum.h"
22#include "TFriendElement.h"
23#include "TFriendProxy.h"
24#include "TLeaf.h"
25#include "TList.h"
26#include "TROOT.h"
27#include "TStreamerInfo.h"
28#include "TStreamerElement.h"
29#include "TTreeReader.h"
30#include "TGenCollectionProxy.h"
31#include "TRegexp.h"
32
33#include <memory>
34#include <optional>
35#include <iostream>
36
37// pin vtable
39
40namespace {
41using namespace ROOT::Internal;
42
43// Reader interface for clones arrays
44class TClonesReader : public TVirtualCollectionReader {
45public:
46 ~TClonesReader() override {}
48 {
49 if (!proxy->Read()) {
51 if (!proxy->GetSuppressErrorsForMissingBranch())
52 Error("TClonesReader::GetCA()", "Read error in TBranchProxy.");
53 return nullptr;
54 }
56 return (TClonesArray *)proxy->GetWhere();
57 }
58 size_t GetSize(ROOT::Detail::TBranchProxy *proxy) override
59 {
61 if (myClonesArray) {
62 return myClonesArray->GetEntries();
63 } else
64 return 0;
65 }
66 void *At(ROOT::Detail::TBranchProxy *proxy, size_t idx) override
67 {
69 if (myClonesArray) {
70 return myClonesArray->UncheckedAt(idx);
71 } else
72 return nullptr;
73 }
74
75 bool IsContiguous(ROOT::Detail::TBranchProxy *) override { return false; }
76
77 std::size_t GetValueSize(ROOT::Detail::TBranchProxy *proxy) override
78 {
79 auto *ca = GetCA(proxy);
80 return ca ? ca->GetClass()->Size() : 0;
81 }
82};
83
85{
86 if (cp.GetProperties() & TVirtualCollectionProxy::kIsEmulated)
87 return true;
88
89 switch (cp.GetCollectionType()) {
91 case ROOT::kROOTRVec: return true;
92 default: return false;
93 }
94}
95
97{
98 // This works only if the collection proxy value type is a fundamental type
99 auto &&eDataType = cp.GetType();
101 return tDataType ? tDataType->Size() : 0;
102}
103
104// Reader interface for STL
105class TSTLReader final : public TVirtualCollectionReader {
106public:
107 ~TSTLReader() override {}
109 {
110 if (!proxy->Read()) {
112 if (!proxy->GetSuppressErrorsForMissingBranch())
113 Error("TSTLReader::GetCP()", "Read error in TBranchProxy.");
114 return nullptr;
115 }
116 if (!proxy->GetWhere()) {
117 Error("TSTLReader::GetCP()", "Logic error, proxy object not set in TBranchProxy.");
118 return nullptr;
119 }
121 return (TVirtualCollectionProxy *)proxy->GetCollection();
122 }
123
124 size_t GetSize(ROOT::Detail::TBranchProxy *proxy) override
125 {
128 return 0;
129 return myCollectionProxy->Size();
130 }
131
132 void *At(ROOT::Detail::TBranchProxy *proxy, size_t idx) override
133 {
136 return nullptr;
137 if (myCollectionProxy->HasPointers()) {
138 return *(void **)myCollectionProxy->At(idx);
139 } else {
140 return myCollectionProxy->At(idx);
141 }
142 }
143
144 bool IsContiguous(ROOT::Detail::TBranchProxy *proxy) override
145 {
146 auto cp = GetCP(proxy);
147 return IsCPContiguous(*cp);
148 }
149
150 std::size_t GetValueSize(ROOT::Detail::TBranchProxy *proxy) override
151 {
152 auto cp = GetCP(proxy);
153 return GetCPValueSize(*cp);
154 }
155};
156
157class TCollectionLessSTLReader final : public TVirtualCollectionReader {
158private:
159 TVirtualCollectionProxy *fLocalCollection;
160
161public:
162 TCollectionLessSTLReader(TVirtualCollectionProxy *proxy) : fLocalCollection(proxy) {}
163
165 {
166 if (!proxy->Read()) {
168 if (!proxy->GetSuppressErrorsForMissingBranch())
169 Error("TCollectionLessSTLReader::GetCP()", "Read error in TBranchProxy.");
170 return nullptr;
171 }
172 if (!proxy->GetWhere()) {
173 Error("TCollectionLessSTLReader::GetCP()", "Logic error, proxy object not set in TBranchProxy.");
174 return nullptr;
175 }
177 return fLocalCollection;
178 }
179
180 size_t GetSize(ROOT::Detail::TBranchProxy *proxy) override
181 {
184 return 0;
185 /// In the case of std::vector<bool> `PushProxy` also creates a temporary bool variable the address of which
186 /// is returned from these calls.
187 myCollectionProxy->PopProxy();
188 myCollectionProxy->PushProxy(proxy->GetWhere());
189 return myCollectionProxy->Size();
190 }
191
192 void *At(ROOT::Detail::TBranchProxy *proxy, size_t idx) override
193 {
196 return nullptr;
197 // Here we do not use a RAII but we empty the proxy to then fill it.
198 // This is done because we are returning a pointer and we need to keep
199 // alive the memory it points to.
200 myCollectionProxy->PopProxy();
201 myCollectionProxy->PushProxy(proxy->GetWhere());
202 if (myCollectionProxy->HasPointers()) {
203 return *(void **)myCollectionProxy->At(idx);
204 } else {
205 return myCollectionProxy->At(idx);
206 }
207 }
208
209 bool IsContiguous(ROOT::Detail::TBranchProxy *proxy) override
210 {
211 auto cp = GetCP(proxy);
212 return IsCPContiguous(*cp);
213 }
214
215 std::size_t GetValueSize(ROOT::Detail::TBranchProxy *proxy) override
216 {
217 auto cp = GetCP(proxy);
218 return GetCPValueSize(*cp);
219 }
220};
221
222// Reader interface for leaf list
223// SEE TTreeProxyGenerator.cxx:1319: '//We have a top level raw type'
224class TObjectArrayReader : public TVirtualCollectionReader {
225private:
226 Int_t fBasicTypeSize;
227
228public:
229 TObjectArrayReader() : fBasicTypeSize(-1) {}
230 ~TObjectArrayReader() override {}
232 {
233 if (!proxy->Read()) {
235 if (!proxy->GetSuppressErrorsForMissingBranch())
236 Error("TObjectArrayReader::GetCP()", "Read error in TBranchProxy.");
237 return nullptr;
238 }
240 return (TVirtualCollectionProxy *)proxy->GetCollection();
241 }
242 size_t GetSize(ROOT::Detail::TBranchProxy *proxy) override
243 {
246 return 0;
247 return myCollectionProxy->Size();
248 }
249 void *At(ROOT::Detail::TBranchProxy *proxy, size_t idx) override
250 {
251 if (!proxy->Read())
252 return nullptr;
253
255 void *array = (void *)proxy->GetStart();
256
257 if (fBasicTypeSize == -1) {
258 TClass *myClass = proxy->GetClass();
259 if (!myClass) {
260 Error("TObjectArrayReader::At()", "Cannot get class info from branch proxy.");
261 return nullptr;
262 }
263 objectSize = myClass->GetClassSize();
264 } else {
265 objectSize = fBasicTypeSize;
266 }
267 return (void *)((Byte_t *)array + (objectSize * idx));
268 }
269
270 void SetBasicTypeSize(Int_t size) { fBasicTypeSize = size; }
271
272 bool IsContiguous(ROOT::Detail::TBranchProxy *) override { return true; }
273
274 std::size_t GetValueSize(ROOT::Detail::TBranchProxy *proxy) override
275 {
276 auto cp = GetCP(proxy);
277 if (cp)
278 return GetCPValueSize(*cp);
279 else
280 return proxy->GetValueSize();
281 }
282};
283
284template <class BASE>
285class TDynamicArrayReader : public BASE {
286
287 // TVirtualSizeReaderImpl and TSizeReaderImpl type-erase the reading of the size leaf.
288 class TVirtualSizeReaderImpl {
289 public:
290 virtual ~TVirtualSizeReaderImpl() = default;
291 virtual size_t GetSize() = 0;
292 };
293
294 template <typename T>
295 class TSizeReaderImpl final : public TVirtualSizeReaderImpl {
296 TTreeReaderValue<T> fSizeReader;
297
298 public:
299 TSizeReaderImpl(TTreeReader &r, const char *leafName) : fSizeReader(r, leafName) {}
300 size_t GetSize() final { return *fSizeReader; }
301 };
302
303 std::unique_ptr<TVirtualSizeReaderImpl> fSizeReader;
304
305public:
306 template <class... ARGS>
307 TDynamicArrayReader(TTreeReader *treeReader, const char *leafName, ARGS &&...args)
308 : BASE(std::forward<ARGS>(args)...)
309 {
310 std::string foundLeafName = leafName;
311 TLeaf *sizeLeaf = treeReader->GetTree()->FindLeaf(foundLeafName.c_str());
312
313 if (!sizeLeaf) {
314 // leafName might be "top.currentParent.N". But "N" might really be "top.N"!
315 // Strip parents until we find the leaf.
316 std::string leafNameNoParent = leafName;
317 std::string parent;
318 auto posLastDot = leafNameNoParent.rfind('.');
319 if (posLastDot != leafNameNoParent.npos) {
320 parent = leafNameNoParent.substr(0, posLastDot);
321 leafNameNoParent.erase(0, posLastDot + 1);
322 }
323
324 do {
325 if (!sizeLeaf && !parent.empty()) {
326 auto posLastDotParent = parent.rfind('.');
327 if (posLastDotParent != parent.npos)
328 parent = parent.substr(0, posLastDot);
329 else
330 parent.clear();
331 }
332
333 foundLeafName = parent;
334 if (!parent.empty())
335 foundLeafName += ".";
337 sizeLeaf = treeReader->GetTree()->FindLeaf(foundLeafName.c_str());
338 } while (!sizeLeaf && !parent.empty());
339 }
340
341 if (!sizeLeaf) {
342 Error("TDynamicArrayReader ", "Cannot find leaf count for %s or any parent branch!", leafName);
343 return;
344 }
345
346 const std::string leafType = sizeLeaf->GetTypeName();
347 if (leafType == "Int_t") {
348 fSizeReader.reset(new TSizeReaderImpl<Int_t>(*treeReader, foundLeafName.c_str()));
349 } else if (leafType == "UInt_t") {
350 fSizeReader.reset(new TSizeReaderImpl<UInt_t>(*treeReader, foundLeafName.c_str()));
351 } else if (leafType == "Short_t") {
352 fSizeReader.reset(new TSizeReaderImpl<Short_t>(*treeReader, foundLeafName.c_str()));
353 } else if (leafType == "UShort_t") {
354 fSizeReader.reset(new TSizeReaderImpl<UShort_t>(*treeReader, foundLeafName.c_str()));
355 } else if (leafType == "Long_t") {
356 fSizeReader.reset(new TSizeReaderImpl<Long_t>(*treeReader, foundLeafName.c_str()));
357 } else if (leafType == "ULong_t") {
358 fSizeReader.reset(new TSizeReaderImpl<ULong_t>(*treeReader, foundLeafName.c_str()));
359 } else if (leafType == "Long64_t") {
360 fSizeReader.reset(new TSizeReaderImpl<Long64_t>(*treeReader, foundLeafName.c_str()));
361 } else if (leafType == "ULong64_t") {
362 fSizeReader.reset(new TSizeReaderImpl<ULong64_t>(*treeReader, foundLeafName.c_str()));
363 } else {
364 Error("TDynamicArrayReader ",
365 "Unsupported size type for leaf %s. Supported types are int, short int, long int, long long int and "
366 "their unsigned counterparts.",
367 leafName);
368 }
369 }
370
371 size_t GetSize(ROOT::Detail::TBranchProxy * /*proxy*/) override { return fSizeReader->GetSize(); }
372};
373
374class TArrayParameterSizeReader : public TDynamicArrayReader<TObjectArrayReader> {
375public:
376 TArrayParameterSizeReader(TTreeReader *treeReader, const char *branchName)
377 : TDynamicArrayReader<TObjectArrayReader>(treeReader, branchName)
378 {
379 }
380};
381
382// Reader interface for fixed size arrays
383class TArrayFixedSizeReader : public TObjectArrayReader {
384private:
385 Int_t fSize;
386
387public:
388 TArrayFixedSizeReader(Int_t sizeArg) : fSize(sizeArg) {}
389
390 size_t GetSize(ROOT::Detail::TBranchProxy * /*proxy*/) override { return fSize; }
391};
392
393class TBasicTypeArrayReader final : public TVirtualCollectionReader {
394public:
395 ~TBasicTypeArrayReader() override {}
396
398 {
399 if (!proxy->Read()) {
401 if (!proxy->GetSuppressErrorsForMissingBranch())
402 Error("TBasicTypeArrayReader::GetCP()", "Read error in TBranchProxy.");
403 return nullptr;
404 }
406 return (TVirtualCollectionProxy *)proxy->GetCollection();
407 }
408
409 size_t GetSize(ROOT::Detail::TBranchProxy *proxy) override
410 {
413 return 0;
414 return myCollectionProxy->Size();
415 }
416
417 void *At(ROOT::Detail::TBranchProxy *proxy, size_t idx) override
418 {
421 return nullptr;
422 return (Byte_t *)myCollectionProxy->At(idx) + proxy->GetOffset();
423 }
424
425 bool IsContiguous(ROOT::Detail::TBranchProxy *) override { return false; }
426
427 std::size_t GetValueSize(ROOT::Detail::TBranchProxy *proxy) override
428 {
429 if (!proxy->Read()) {
431 if (!proxy->GetSuppressErrorsForMissingBranch())
432 Error("TBasicTypeArrayReader::GetValueSize()", "Read error in TBranchProxy.");
433 return 0;
434 }
436 return proxy->GetValueSize();
437 }
438};
439
440class TBasicTypeClonesReader final : public TClonesReader {
441private:
442 Int_t fOffset;
443
444public:
445 TBasicTypeClonesReader(Int_t offsetArg) : fOffset(offsetArg) {}
446
447 void *At(ROOT::Detail::TBranchProxy *proxy, size_t idx) override
448 {
450 if (!myClonesArray)
451 return nullptr;
452 return (Byte_t *)myClonesArray->At(idx) + fOffset;
453 }
454};
455
456class TLeafReader : public TVirtualCollectionReader {
457private:
458 TTreeReaderValueBase *fValueReader;
459 Int_t fElementSize;
460
461public:
462 TLeafReader(TTreeReaderValueBase *valueReaderArg) : fValueReader(valueReaderArg), fElementSize(-1) {}
463
464 size_t GetSize(ROOT::Detail::TBranchProxy * /*proxy*/) override
465 {
466 TLeaf *myLeaf = fValueReader->GetLeaf();
467 return myLeaf ? myLeaf->GetLen() : 0; // Error will be printed by GetLeaf
468 }
469
470 void *At(ROOT::Detail::TBranchProxy * /*proxy*/, size_t idx) override
471 {
472 ProxyRead();
473 void *address = fValueReader->GetAddress();
474 if (fElementSize == -1) {
475 TLeaf *myLeaf = fValueReader->GetLeaf();
476 if (!myLeaf)
477 return nullptr; // Error will be printed by GetLeaf
478 fElementSize = myLeaf->GetLenType();
479 }
480 return (Byte_t *)address + (fElementSize * idx);
481 }
482
483 bool IsContiguous(ROOT::Detail::TBranchProxy *) override { return true; }
484
485 std::size_t GetValueSize(ROOT::Detail::TBranchProxy *) override
486 {
487 auto *leaf = fValueReader->GetLeaf();
488 return leaf ? leaf->GetLenType() : 0;
489 }
490
491protected:
492 void ProxyRead() { fValueReader->ProxyRead(); }
493};
494
495class TLeafParameterSizeReader : public TDynamicArrayReader<TLeafReader> {
496public:
497 TLeafParameterSizeReader(TTreeReader *treeReader, const char *leafName, TTreeReaderValueBase *valueReaderArg)
498 : TDynamicArrayReader<TLeafReader>(treeReader, leafName, valueReaderArg)
499 {
500 }
501
502 size_t GetSize(ROOT::Detail::TBranchProxy *proxy) override
503 {
504 ProxyRead();
505 return TDynamicArrayReader<TLeafReader>::GetSize(proxy);
506 }
507};
508} // namespace
509
511
512////////////////////////////////////////////////////////////////////////////////
513/// Create the proxy object for our branch.
514
516{
517 if (fProxy) {
518 return;
519 }
520
521 fSetupStatus = kSetupInternalError; // Fallback; set to something concrete below.
522 if (!fTreeReader) {
523 Error("TTreeReaderArrayBase::CreateProxy()", "TTreeReader object not set / available for branch %s!",
524 fBranchName.Data());
525 fSetupStatus = kSetupTreeDestructed;
526 return;
527 }
528 if (!fDict) {
529 TBranch *br = fTreeReader->GetTree()->GetBranch(fBranchName);
530 const char *brDataType = "{UNDETERMINED}";
531 if (br) {
532 TDictionary *dictUnused = nullptr;
533 brDataType = GetBranchDataType(br, dictUnused, fDict);
534 }
535 Error("TTreeReaderArrayBase::CreateProxy()",
536 "The template argument type T of %s accessing branch %s (which contains data of type %s) is not known to "
537 "ROOT. You will need to create a dictionary for it.",
538 GetDerivedTypeName(), fBranchName.Data(), brDataType);
539 fSetupStatus = kSetupMissingDictionary;
540 return;
541 }
542
543 // Access a branch's collection content (not the collection itself)
544 // through a proxy.
545 // Search for the branchname, determine what it contains, and wire the
546 // TBranchProxy representing it to us so we can access its data.
547
548 // Tell the branch proxy to suppress the errors for missing branch if this
549 // branch name is found in the list of suppressions
550 const bool suppressErrorsForThisBranch = (fTreeReader->fSuppressErrorsForMissingBranches.find(fBranchName.Data()) !=
551 fTreeReader->fSuppressErrorsForMissingBranches.cend());
552
553 TDictionary *branchActualType = nullptr;
554 TBranch *branch = nullptr;
555 TLeaf *myLeaf = nullptr;
557 return;
558
559 if (!fDict) {
560 Error("TTreeReaderArrayBase::CreateProxy()", "No dictionary for branch %s.", fBranchName.Data());
561 return;
562 }
563
564 TNamedBranchProxy *namedProxy = fTreeReader->FindProxy(fBranchName);
565 if (namedProxy) {
566 if (namedProxy->GetContentDict() == fDict) {
567 fSetupStatus = kSetupMatch;
568 fProxy = namedProxy->GetProxy();
569 SetImpl(branch, myLeaf);
570 return;
571 }
572
573 // Update named proxy's dictionary
574 if (!namedProxy->GetContentDict()) {
575 namedProxy->SetContentDict(fDict);
576 fProxy = namedProxy->GetProxy();
577 if (fProxy)
578 fSetupStatus = kSetupMatch;
579 } else {
580 Error("TTreeReaderArrayBase::CreateProxy()", "Type ambiguity (want %s, have %s) for branch %s.",
581 fDict->GetName(), namedProxy->GetContentDict()->GetName(), fBranchName.Data());
582 }
583 } else {
585
586 bool isTopLevel = branch->GetMother() == branch;
587 if (!isTopLevel) {
588 membername = strrchr(branch->GetName(), '.');
589 if (membername.IsNull()) {
590 membername = branch->GetName();
591 }
592 }
593 auto *director = fTreeReader->fDirector.get();
594 // Determine if the branch is actually in a Friend TTree and if so which.
595 if (branch->GetTree() != fTreeReader->GetTree()->GetTree()) {
596 // It is in a friend, let's find the 'index' in the list of friend ...
597 std::optional<std::size_t> index;
598 std::size_t current{};
599 auto &&friends = fTreeReader->GetTree()->GetTree()->GetListOfFriends();
601 if (branch->GetTree() == fe->GetTree()) {
602 index = current;
603 break;
604 }
605 ++current;
606 }
607 if (!index.has_value()) {
608 Error("TTreeReaderArrayBase::CreateProxy()",
609 "The branch %s is contained in a Friend TTree that is not directly attached to the main.\n"
610 "This is not yet supported by TTreeReader.",
611 fBranchName.Data());
612 return;
613 }
614
615 auto &&friendProxy = fTreeReader->AddFriendProxy(index.value());
616 director = friendProxy.GetDirector();
617 }
618 fTreeReader->AddProxy(
619 std::make_unique<TNamedBranchProxy>(director, branch, fBranchName, membername, suppressErrorsForThisBranch));
620
621 namedProxy = fTreeReader->FindProxy(fBranchName);
622 fProxy = namedProxy->GetProxy();
623 if (fProxy)
624 fSetupStatus = kSetupMatch;
625 else
626 fSetupStatus = kSetupMismatch;
627 }
628
629 if (!myLeaf) {
631 const char *nonCollTypeName = GetBranchContentDataType(branch, branchActualTypeName, branchActualType);
632 if (nonCollTypeName) {
633 Error("TTreeReaderArrayBase::CreateContentProxy()",
634 "The branch %s contains data of type %s, which should be accessed through a TTreeReaderValue< %s >.",
635 fBranchName.Data(), nonCollTypeName, nonCollTypeName);
636 if (fSetupStatus == kSetupInternalError)
637 fSetupStatus = kSetupNotACollection;
638 fProxy = nullptr;
639 return;
640 }
641 if (!branchActualType) {
642 if (branchActualTypeName.IsNull()) {
643 Error("TTreeReaderArrayBase::CreateContentProxy()",
644 "Cannot determine the type contained in the collection of branch %s. That's weird - please report!",
645 fBranchName.Data());
646 } else {
647 Error("TTreeReaderArrayBase::CreateContentProxy()",
648 "The branch %s contains data of type %s, which does not have a dictionary.", fBranchName.Data(),
649 branchActualTypeName.Data());
650 if (fSetupStatus == kSetupInternalError)
651 fSetupStatus = kSetupMissingDictionary;
652 }
653 fProxy = nullptr;
654 return;
655 }
656
657 auto matchingDataType = [](TDictionary *left, TDictionary *right) -> bool {
658 if (left == right)
659 return true;
660 if (!left || !right)
661 return false;
662 auto left_datatype = dynamic_cast<TDataType *>(left);
663 auto right_datatype = dynamic_cast<TDataType *>(right);
664 auto left_enum = dynamic_cast<TEnum *>(left);
665 auto right_enum = dynamic_cast<TEnum *>(right);
666
667 if ((left_datatype && left_datatype->GetType() == kInt_t && right_enum) ||
668 (right_datatype && right_datatype->GetType() == kInt_t && left_enum))
669 return true;
670 if ((left_datatype && right_enum && left_datatype->GetType() == right_enum->GetUnderlyingType()) ||
671 (right_datatype && left_enum && right_datatype->GetType() == left_enum->GetUnderlyingType()))
672 return true;
674 return false;
675 auto l = left_datatype->GetType();
676 auto r = right_datatype->GetType();
677 if (l > 0 && l == r)
678 return true;
679 else
680 return ((l == kDouble32_t && r == kDouble_t) || (l == kDouble_t && r == kDouble32_t) ||
681 (l == kFloat16_t && r == kFloat_t) || (l == kFloat_t && r == kFloat16_t));
682 };
683
684 if (!matchingDataType(fDict, branchActualType)) {
685 Error("TTreeReaderArrayBase::CreateContentProxy()",
686 "The branch %s contains data of type %s. It cannot be accessed by a TTreeReaderArray<%s>",
687 fBranchName.Data(), branchActualType->GetName(), fDict->GetName());
688 if (fSetupStatus == kSetupInternalError || fSetupStatus >= 0)
689 fSetupStatus = kSetupMismatch;
690
691 // Update named proxy's dictionary
692 if (!namedProxy->GetContentDict()) {
693 namedProxy->SetContentDict(fDict);
694 }
695
696 // fProxy = 0;
697 // return;
698 }
699 }
700
701 SetImpl(branch, myLeaf);
702}
703
704////////////////////////////////////////////////////////////////////////////////
705/// Determine the branch / leaf and its type; reset fProxy / fSetupStatus on error.
706
710{
711 myLeaf = nullptr;
712 branch = fTreeReader->GetTree()->GetBranch(fBranchName);
713 if (branch)
714 return true;
715
716 if (!fBranchName.Contains(".")) {
718 Error("TTreeReaderArrayBase::GetBranchAndLeaf()",
719 "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.",
720 fBranchName.Data());
721 }
722 fSetupStatus = kSetupMissingBranch;
723 fProxy = nullptr;
724 return false;
725 }
726
727 TRegexp leafNameExpression("\.[a-zA-Z0-9_]+$");
728 TString leafName(fBranchName(leafNameExpression));
729 TString branchName = fBranchName(0, fBranchName.Length() - leafName.Length());
730 branch = fTreeReader->GetTree()->GetBranch(branchName);
731 if (!branch) {
733 Error("TTreeReaderArrayBase::GetBranchAndLeaf()",
734 "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.",
735 fBranchName.Data());
736 }
737 fSetupStatus = kSetupMissingBranch;
738 fProxy = nullptr;
739 return false;
740 }
741
742 myLeaf = branch->GetLeaf(TString(leafName(1, leafName.Length())));
743 if (!myLeaf) {
745 Error("TTreeReaderArrayBase::GetBranchAndLeaf()",
746 "The tree does not have a branch, nor a sub-branch called %s. You could check with TTree::Print() for "
747 "available branches.",
748 fBranchName.Data());
749 }
750 fSetupStatus = kSetupMissingBranch;
751 fProxy = nullptr;
752 return false;
753 }
754
756 if (!tempDict) {
757 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Failed to get the dictionary for %s.", myLeaf->GetTypeName());
758 fSetupStatus = kSetupMissingDictionary;
759 fProxy = nullptr;
760 return false;
761 }
762
763 if (tempDict->IsA() == TDataType::Class() &&
764 TDictionary::GetDictionary(((TDataType *)tempDict)->GetTypeName()) == fDict) {
765 // fLeafOffset = myLeaf->GetOffset() / 4;
766 branchActualType = fDict;
767 fLeaf = myLeaf;
768 fBranchName = branchName;
769 fLeafName = leafName(1, leafName.Length());
770 fHaveLeaf = (fLeafName.Length() > 0);
771 fSetupStatus = kSetupMatchLeaf;
772 } else {
773 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Leaf of type %s cannot be read by TTreeReaderValue<%s>.",
774 myLeaf->GetTypeName(), fDict->GetName());
775 fProxy = nullptr;
776 fSetupStatus = kSetupMismatch;
777 return false;
778 }
779 return true;
780}
781
782////////////////////////////////////////////////////////////////////////////////
783/// Create the TVirtualCollectionReader object for our branch.
784
786{
787 if (fImpl)
788 return;
789
790 // Access a branch's collection content (not the collection itself)
791 // through a proxy.
792 // Search for the branchname, determine what it contains, and wire the
793 // TBranchProxy representing it to us so we can access its data.
794 // A proxy for branch must not have been created before (i.e. check
795 // fProxies before calling this function!)
796
797 if (myLeaf) {
798 if (!myLeaf->GetLeafCount()) {
799 fImpl = std::make_unique<TLeafReader>(this);
800 } else {
801 TString leafFullName = myLeaf->GetBranch()->GetName();
802 leafFullName += ".";
803 leafFullName += myLeaf->GetLeafCount()->GetName();
804 fImpl = std::make_unique<TLeafParameterSizeReader>(fTreeReader, leafFullName.Data(), this);
805 }
806 fSetupStatus = kSetupMatchLeaf;
807 } else if (branch->IsA() == TBranchElement::Class()) {
809
811 Int_t id = branchElement->GetID();
812
813 if (id >= 0) { // Not root node?
814 // Int_t offset = streamerInfo->GetOffsets()[id];
815 TStreamerElement *element = (TStreamerElement *)streamerInfo->GetElements()->At(id);
816 // bool isPointer = element->IsaPointer();
817 // TClass *classPointer = element->GetClassPointer();
818
819 if (fSetupStatus == kSetupInternalError)
820 fSetupStatus = kSetupMatch;
821 if (element->IsA() == TStreamerSTL::Class()) {
822 if (branchElement->GetType() == 31) {
823 Error("TTreeReaderArrayBase::SetImpl", "STL Collection nested in a TClonesArray not yet supported");
824 fSetupStatus = kSetupInternalError;
825 return;
826 }
827 fImpl = std::make_unique<TSTLReader>();
828 } else if (element->IsA() == TStreamerObject::Class()) {
829 // fImpl = new TObjectArrayReader(); // BArray[12]
830
831 if (element->GetClass() == TClonesArray::Class()) {
832 fImpl = std::make_unique<TClonesReader>();
833 } else if (branchElement->GetType() == TBranchElement::kSTLMemberNode) {
834 fImpl = std::make_unique<TBasicTypeArrayReader>();
835 } else if (branchElement->GetType() == TBranchElement::kClonesMemberNode) {
836 // TBasicTypeClonesReader should work for object
837 fImpl = std::make_unique<TBasicTypeClonesReader>(element->GetOffset());
838 } else {
839 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
840 }
841 } else if (element->IsA() == TStreamerLoop::Class()) {
842 fImpl =
843 std::make_unique<TArrayParameterSizeReader>(fTreeReader, branchElement->GetBranchCount()->GetName());
844 } else if (element->IsA() == TStreamerBasicType::Class()) {
846 fImpl = std::make_unique<TBasicTypeArrayReader>();
847 } else if (branchElement->GetType() == TBranchElement::kClonesMemberNode) {
848 fImpl = std::make_unique<TBasicTypeClonesReader>(element->GetOffset());
849 } else if (fDict->IsA() == TEnum::Class()) {
850 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
851 ((TObjectArrayReader *)fImpl.get())->SetBasicTypeSize(sizeof(Int_t));
852 } else {
853 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
854 ((TObjectArrayReader *)fImpl.get())->SetBasicTypeSize(((TDataType *)fDict)->Size());
855 }
856 } else if (element->IsA() == TStreamerBasicPointer::Class()) {
857 fImpl =
858 std::make_unique<TArrayParameterSizeReader>(fTreeReader, branchElement->GetBranchCount()->GetName());
859 ((TArrayParameterSizeReader *)fImpl.get())->SetBasicTypeSize(((TDataType *)fDict)->Size());
860 } else if (element->IsA() == TStreamerBase::Class()) {
861 fImpl = std::make_unique<TClonesReader>();
862 } else {
863 Error("TTreeReaderArrayBase::SetImpl()", "Cannot read branch %s: unhandled streamer element type %s",
864 fBranchName.Data(), element->IsA()->GetName());
865 fSetupStatus = kSetupInternalError;
866 }
867 } else { // We are at root node?
868 if (branchElement->GetClass()->GetCollectionProxy()) {
869 fImpl = std::make_unique<TCollectionLessSTLReader>(branchElement->GetClass()->GetCollectionProxy());
870 }
871 }
872 } else if (branch->IsA() == TBranch::Class()) {
873 auto topLeaf = branch->GetLeaf(branch->GetName());
874 if (!topLeaf) {
875 Error("TTreeReaderArrayBase::SetImpl", "Failed to get the top leaf from the branch");
876 fSetupStatus = kSetupMissingBranch;
877 return;
878 }
879 // We could have used GetLeafCounter, but it does not work well with Double32_t and Float16_t: ROOT-10149
880 auto sizeLeaf = topLeaf->GetLeafCount();
881 if (fSetupStatus == kSetupInternalError)
882 fSetupStatus = kSetupMatch;
883 if (!sizeLeaf) {
884 fImpl = std::make_unique<TArrayFixedSizeReader>(topLeaf->GetLenStatic());
885 } else {
886 fImpl = std::make_unique<TArrayParameterSizeReader>(fTreeReader, sizeLeaf->GetName());
887 }
888 ((TObjectArrayReader *)fImpl.get())->SetBasicTypeSize(((TDataType *)fDict)->Size());
889 } else if (branch->IsA() == TBranchClones::Class()) {
890 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchClones not implemented");
891 fSetupStatus = kSetupInternalError;
892 } else if (branch->IsA() == TBranchObject::Class()) {
893 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchObject not implemented");
894 fSetupStatus = kSetupInternalError;
895 } else if (branch->IsA() == TBranchSTL::Class()) {
896 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchSTL not implemented");
897 fImpl = std::make_unique<TSTLReader>();
898 fSetupStatus = kSetupInternalError;
899 } else if (branch->IsA() == TBranchRef::Class()) {
900 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchRef not implemented");
901 fSetupStatus = kSetupInternalError;
902 }
903}
904
905////////////////////////////////////////////////////////////////////////////////
906/// Access a branch's collection content (not the collection itself)
907/// through a proxy.
908/// Retrieve the type of data contained in the collection stored by branch;
909/// put its dictionary into dict, If there is no dictionary, put its type
910/// name into contentTypeName.
911/// The contentTypeName is set to NULL if the branch does not
912/// contain a collection; in that case, the type of the branch is returned.
913/// In all other cases, NULL is returned.
914
916 TDictionary *&dict)
917{
918 dict = nullptr;
919 contentTypeName = "";
920 if (branch->IsA() == TBranchElement::Class()) {
922 if (brElement->GetType() == 4 || brElement->GetType() == 3) {
923 TVirtualCollectionProxy *collProxy = brElement->GetCollectionProxy();
924 if (collProxy) {
925 TClass *myClass = collProxy->GetValueClass();
926 if (!myClass) {
927 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Could not get value class.");
928 return nullptr;
929 }
930 dict = TDictionary::GetDictionary(myClass->GetName());
931 if (!dict)
932 dict = TDataType::GetDataType(collProxy->GetType());
933 }
934 if (!dict) {
935 // We don't know the dictionary, thus we need the content's type name.
936 // Determine it.
937 if (brElement->GetType() == 3) {
938 contentTypeName = brElement->GetClonesName();
939 dict = TDictionary::GetDictionary(brElement->GetClonesName());
940 return nullptr;
941 }
942 // STL:
944 int isSTLCont = splitType.IsSTLCont();
945 if (!isSTLCont) {
946 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
947 "Cannot determine STL collection type of %s stored in branch %s", brElement->GetClassName(),
948 branch->GetName());
949 return brElement->GetClassName();
950 }
952 if (isMap)
953 contentTypeName = "std::pair< ";
954 contentTypeName += splitType.fElements[1];
955 if (isMap) {
956 contentTypeName += splitType.fElements[2];
957 contentTypeName += " >";
958 }
959 return nullptr;
960 }
961 return nullptr;
962 } else if (brElement->GetType() == 31 || brElement->GetType() == 41) {
963 // it's a member, extract from GetClass()'s streamer info
964 TClass *clData = nullptr;
966 int ExpectedTypeRet = brElement->GetExpectedType(clData, dtData);
967 if (ExpectedTypeRet == 0) {
968 dict = clData;
969 if (!dict) {
970 if (dtData == kFloat16_t) {
972 }
973 if (dtData == kDouble32_t) {
975 }
977 }
978 if (!dict) {
979 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
980 "The branch %s contains a data type %d for which the dictionary cannot be retrieved.",
981 branch->GetName(), (int)dtData);
983 return nullptr;
984 }
985 return nullptr;
986 } else if (ExpectedTypeRet == 1) {
987 int brID = brElement->GetID();
988 if (brID == -1) {
989 // top
990 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
991 "The branch %s contains data of type %s for which the dictionary does not exist. It's needed.",
992 branch->GetName(), brElement->GetClassName());
993 contentTypeName = brElement->GetClassName();
994 return nullptr;
995 }
996 // Either the data type name doesn't have an EDataType entry
997 // or the streamer info doesn't have a TClass* attached.
998 TStreamerElement *element = (TStreamerElement *)brElement->GetInfo()->GetElement(brID);
999 contentTypeName = element->GetTypeName();
1000 return nullptr;
1001 }
1002 /* else (ExpectedTypeRet == 2)*/
1003 // The streamer info entry cannot be found.
1004 // TBranchElement::GetExpectedType() has already complained.
1005 return "{CANNOT DETERMINE TBranchElement DATA TYPE}";
1006 } else if (brElement->GetType() == TBranchElement::kLeafNode) {
1007 TStreamerInfo *streamerInfo = brElement->GetInfo();
1008 Int_t id = brElement->GetID();
1009
1010 if (id >= 0) {
1011 TStreamerElement *element = (TStreamerElement *)streamerInfo->GetElements()->At(id);
1012
1013 if (element->IsA() == TStreamerSTL::Class()) {
1014 TClass *myClass = brElement->GetCurrentClass();
1015 if (!myClass) {
1016 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get class from branch element.");
1017 return nullptr;
1018 }
1019 TVirtualCollectionProxy *myCollectionProxy = myClass->GetCollectionProxy();
1020 if (!myCollectionProxy) {
1021 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get collection proxy from STL class");
1022 return nullptr;
1023 }
1024 // Try getting the contained class
1025 dict = myCollectionProxy->GetValueClass();
1026 // If it fails, try to get the contained type as a primitive type
1027 if (!dict)
1028 dict = TDataType::GetDataType(myCollectionProxy->GetType());
1029 if (!dict) {
1030 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get valueClass from collectionProxy.");
1031 return nullptr;
1032 }
1033 contentTypeName = dict->GetName();
1034 return nullptr;
1035 } else if (element->IsA() == TStreamerObject::Class() && !strcmp(element->GetTypeName(), "TClonesArray")) {
1036 if (!fProxy->Setup() || !fProxy->Read()) {
1037 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
1038 "Failed to get type from proxy, unable to check type");
1039 contentTypeName = "UNKNOWN";
1040 dict = nullptr;
1041 return contentTypeName;
1042 }
1043 TClonesArray *myArray = (TClonesArray *)fProxy->GetWhere();
1044 dict = myArray->GetClass();
1045 contentTypeName = dict->GetName();
1046 return nullptr;
1047 } else {
1048 dict = brElement->GetCurrentClass();
1049 if (!dict) {
1051 dict = TDataType::GetDataType((EDataType)((TDataType *)myDataType)->GetType());
1052 }
1053 contentTypeName = brElement->GetTypeName();
1054 return nullptr;
1055 }
1056 }
1057 if (brElement->GetCurrentClass() == TClonesArray::Class()) {
1058 contentTypeName = "TClonesArray";
1059 Warning("TTreeReaderArrayBase::GetBranchContentDataType()",
1060 "Not able to check type correctness, ignoring check");
1061 dict = fDict;
1062 fSetupStatus = kSetupNoCheck;
1063 } else if (!dict && (branch->GetSplitLevel() == 0 || brElement->GetClass()->GetCollectionProxy())) {
1064 // Try getting the contained class
1065 dict = brElement->GetClass()->GetCollectionProxy()->GetValueClass();
1066 // If it fails, try to get the contained type as a primitive type
1067 if (!dict)
1068 dict = TDataType::GetDataType(brElement->GetClass()->GetCollectionProxy()->GetType());
1069 if (dict)
1070 contentTypeName = dict->GetName();
1071 return nullptr;
1072 } else if (!dict) {
1073 dict = brElement->GetClass();
1074 contentTypeName = dict->GetName();
1075 return nullptr;
1076 }
1077
1078 return nullptr;
1079 }
1080 return nullptr;
1081 } else if (branch->IsA() == TBranch::Class() || branch->IsA() == TBranchObject::Class() ||
1082 branch->IsA() == TBranchSTL::Class()) {
1083 const char *dataTypeName = branch->GetClassName();
1084 if ((!dataTypeName || !dataTypeName[0]) && branch->IsA() == TBranch::Class()) {
1085 auto myLeaf = branch->GetLeaf(branch->GetName());
1086 if (myLeaf) {
1087 auto myDataType = TDictionary::GetDictionary(myLeaf->GetTypeName());
1088 if (myDataType && myDataType->IsA() == TDataType::Class()) {
1089 auto typeEnumConstant = EDataType(((TDataType *)myDataType)->GetType());
1090 // We need to consider Double32_t and Float16_t as dounle and float respectively
1091 // since this is the type the user uses to instantiate the TTreeReaderArray template.
1094 else if (typeEnumConstant == kFloat16_t)
1097 contentTypeName = myLeaf->GetTypeName();
1098 return nullptr;
1099 }
1100 }
1101
1102 // leaflist. Can't represent.
1103 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
1104 "The branch %s was created using a leaf list and cannot be represented as a C++ type. Please access one "
1105 "of its siblings using a TTreeReaderArray:",
1106 branch->GetName());
1107 TIter iLeaves(branch->GetListOfLeaves());
1108 TLeaf *leaf = nullptr;
1109 while ((leaf = (TLeaf *)iLeaves())) {
1110 Error("TTreeReaderArrayBase::GetBranchContentDataType()", " %s.%s", branch->GetName(), leaf->GetName());
1111 }
1112 return nullptr;
1113 }
1114 if (dataTypeName)
1116 if (branch->IsA() == TBranchSTL::Class()) {
1117 Warning("TTreeReaderArrayBase::GetBranchContentDataType()",
1118 "Not able to check type correctness, ignoring check");
1119 dict = fDict;
1120 fSetupStatus = kSetupNoCheck;
1121 return nullptr;
1122 }
1123 return dataTypeName;
1124 } else if (branch->IsA() == TBranchClones::Class()) {
1125 dict = TClonesArray::Class();
1126 return "TClonesArray";
1127 } else if (branch->IsA() == TBranchRef::Class()) {
1128 // Can't represent.
1129 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
1130 "The branch %s is a TBranchRef and cannot be represented as a C++ type.", branch->GetName());
1131 return nullptr;
1132 } else {
1133 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
1134 "The branch %s is of type %s - something that is not handled yet.", branch->GetName(),
1135 branch->IsA()->GetName());
1136 return nullptr;
1137 }
1138
1139 return nullptr;
1140}
dim_t fSize
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define ClassImp(name)
Definition Rtypes.h:374
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
EDataType
Definition TDataType.h:28
@ kFloat_t
Definition TDataType.h:31
@ kInt_t
Definition TDataType.h:30
@ 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:185
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
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.
Base class of TTreeReaderArray.
void CreateProxy() override
Create the proxy object for our branch.
bool GetBranchAndLeaf(TBranch *&branch, TLeaf *&myLeaf, TDictionary *&branchActualType, bool suppressErrorsForMissingBranch=false)
Determine the branch / leaf and its type; reset fProxy / fSetupStatus on error.
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.
static TClass * Class()
static TClass * Class()
static TClass * Class()
static TClass * Class()
A TTree is a list of TBranches.
Definition TBranch.h:93
static TClass * Class()
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
An array of clone (identical) objects.
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".
static TDataType * GetDataType(EDataType type)
Given a EDataType type, get the TDataType* that represents it.
This class defines an abstract interface that must be implemented by all classes that contain diction...
static TDictionary * GetDictionary(const char *name)
Retrieve the type (class, fundamental type, typedef etc) named "name".
The TEnum class implements the enum type.
Definition TEnum.h:33
static TClass * Class()
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition TLeaf.h:57
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Regular expression class.
Definition TRegexp.h:31
static TClass * Class()
static TClass * Class()
static TClass * Class()
Describes a persistent version of a class.
static TClass * Class()
static TClass * Class()
static TClass * Class()
Basic string class.
Definition TString.h:139
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:46
Defines a common interface to inspect/change the contents of an object that represents a collection.
@ kSTLmap
Definition ESTLType.h:33
@ kROOTRVec
Definition ESTLType.h:46
@ kSTLvector
Definition ESTLType.h:30
@ kSTLmultimap
Definition ESTLType.h:34
void forward(const LAYERDATA &prevLayerData, LAYERDATA &currLayerData)
apply the weights (and functions) in forward direction of the DNN
TLine l
Definition textangle.C:4
#define ARGS(alist)
Definition gifencode.c:10