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