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
528
529////////////////////////////////////////////////////////////////////////////////
530/// Create the proxy object for our branch.
531
533{
534 if (fProxy) {
535 return;
536 }
537
538 fSetupStatus = kSetupInternalError; // Fallback; set to something concrete below.
539 if (!fTreeReader) {
540 Error("TTreeReaderArrayBase::CreateProxy()", "TTreeReader object not set / available for branch %s!",
541 fBranchName.Data());
542 fSetupStatus = kSetupTreeDestructed;
543 return;
544 }
545 if (!fDict) {
546 TBranch *br = fTreeReader->GetTree()->GetBranch(fBranchName);
547 const char *brDataType = "{UNDETERMINED}";
548 if (br) {
549 TDictionary *dictUnused = nullptr;
550 brDataType = GetBranchDataType(br, dictUnused, fDict);
551 }
552 Error("TTreeReaderArrayBase::CreateProxy()",
553 "The template argument type T of %s accessing branch %s (which contains data of type %s) is not known to "
554 "ROOT. You will need to create a dictionary for it.",
555 GetDerivedTypeName(), fBranchName.Data(), brDataType);
556 fSetupStatus = kSetupMissingDictionary;
557 return;
558 }
559
560 // Access a branch's collection content (not the collection itself)
561 // through a proxy.
562 // Search for the branchname, determine what it contains, and wire the
563 // TBranchProxy representing it to us so we can access its data.
564
565 // Tell the branch proxy to suppress the errors for missing branch if this
566 // branch name is found in the list of suppressions
567 const bool suppressErrorsForThisBranch = (fTreeReader->fSuppressErrorsForMissingBranches.find(fBranchName.Data()) !=
568 fTreeReader->fSuppressErrorsForMissingBranches.cend());
569
570 TDictionary *branchActualType = nullptr;
571 TBranch *branch = nullptr;
572 TLeaf *myLeaf = nullptr;
574 return;
575
576 if (!fDict) {
577 Error("TTreeReaderArrayBase::CreateProxy()", "No dictionary for branch %s.", fBranchName.Data());
578 return;
579 }
580
581 TNamedBranchProxy *namedProxy = fTreeReader->FindProxy(fBranchName);
582 if (namedProxy) {
583 if (namedProxy->GetContentDict() == fDict) {
584 fSetupStatus = kSetupMatch;
585 fProxy = namedProxy->GetProxy();
586 SetImpl(branch, myLeaf);
587 return;
588 }
589
590 // Update named proxy's dictionary
591 if (!namedProxy->GetContentDict()) {
592 namedProxy->SetContentDict(fDict);
593 fProxy = namedProxy->GetProxy();
594 if (fProxy)
595 fSetupStatus = kSetupMatch;
596 } else {
597 Error("TTreeReaderArrayBase::CreateProxy()", "Type ambiguity (want %s, have %s) for branch %s.",
598 fDict->GetName(), namedProxy->GetContentDict()->GetName(), fBranchName.Data());
599 }
600 } else {
602
603 bool isTopLevel = branch->GetMother() == branch;
604 if (!isTopLevel) {
605 membername = strrchr(branch->GetName(), '.');
606 if (membername.IsNull()) {
607 membername = branch->GetName();
608 }
609 }
610 auto *director = fTreeReader->fDirector.get();
611 // Determine if the branch is actually in a Friend TTree and if so which.
612 if (branch->GetTree() != fTreeReader->GetTree()->GetTree()) {
613 // It is in a friend, let's find the 'index' in the list of friend ...
614 std::optional<std::size_t> index;
615 std::size_t current{};
616 auto &&friends = fTreeReader->GetTree()->GetTree()->GetListOfFriends();
618 if (branch->GetTree() == fe->GetTree()) {
619 index = current;
620 break;
621 }
622 ++current;
623 }
624 if (!index.has_value()) {
625 Error("TTreeReaderArrayBase::CreateProxy()",
626 "The branch %s is contained in a Friend TTree that is not directly attached to the main.\n"
627 "This is not yet supported by TTreeReader.",
628 fBranchName.Data());
629 return;
630 }
631
632 auto &&friendProxy = fTreeReader->AddFriendProxy(index.value());
633 director = friendProxy.GetDirector();
634 }
635 fTreeReader->AddProxy(
636 std::make_unique<TNamedBranchProxy>(director, branch, fBranchName, membername, suppressErrorsForThisBranch));
637
638 namedProxy = fTreeReader->FindProxy(fBranchName);
639 fProxy = namedProxy->GetProxy();
640 if (fProxy)
641 fSetupStatus = kSetupMatch;
642 else
643 fSetupStatus = kSetupMismatch;
644 }
645
646 if (!myLeaf) {
648 const char *nonCollTypeName = GetBranchContentDataType(branch, branchActualTypeName, branchActualType);
649 if (nonCollTypeName) {
650 Error("TTreeReaderArrayBase::CreateContentProxy()",
651 "The branch %s contains data of type %s, which should be accessed through a TTreeReaderValue< %s >.",
652 fBranchName.Data(), nonCollTypeName, nonCollTypeName);
653 if (fSetupStatus == kSetupInternalError)
654 fSetupStatus = kSetupNotACollection;
655 fProxy = nullptr;
656 return;
657 }
658 if (!branchActualType) {
659 if (branchActualTypeName.IsNull()) {
660 Error("TTreeReaderArrayBase::CreateContentProxy()",
661 "Cannot determine the type contained in the collection of branch %s. That's weird - please report!",
662 fBranchName.Data());
663 } else {
664 Error("TTreeReaderArrayBase::CreateContentProxy()",
665 "The branch %s contains data of type %s, which does not have a dictionary.", fBranchName.Data(),
666 branchActualTypeName.Data());
667 if (fSetupStatus == kSetupInternalError)
668 fSetupStatus = kSetupMissingDictionary;
669 }
670 fProxy = nullptr;
671 return;
672 }
673
674 auto matchingDataType = [](TDictionary *left, TDictionary *right) -> bool {
675 if (left == right)
676 return true;
677 if (!left || !right)
678 return false;
679 auto left_datatype = dynamic_cast<TDataType *>(left);
680 auto right_datatype = dynamic_cast<TDataType *>(right);
681 auto left_enum = dynamic_cast<TEnum *>(left);
682 auto right_enum = dynamic_cast<TEnum *>(right);
683
684 if ((left_datatype && left_datatype->GetType() == kInt_t && right_enum) ||
685 (right_datatype && right_datatype->GetType() == kInt_t && left_enum))
686 return true;
687 if ((left_datatype && right_enum && left_datatype->GetType() == right_enum->GetUnderlyingType()) ||
688 (right_datatype && left_enum && right_datatype->GetType() == left_enum->GetUnderlyingType()))
689 return true;
691 return false;
692 auto l = left_datatype->GetType();
693 auto r = right_datatype->GetType();
694 if (l > 0 && l == r)
695 return true;
696 else
697 return ((l == kDouble32_t && r == kDouble_t) || (l == kDouble_t && r == kDouble32_t) ||
698 (l == kFloat16_t && r == kFloat_t) || (l == kFloat_t && r == kFloat16_t));
699 };
700
701 if (!matchingDataType(fDict, branchActualType)) {
702 Error("TTreeReaderArrayBase::CreateContentProxy()",
703 "The branch %s contains data of type %s. It cannot be accessed by a TTreeReaderArray<%s>",
704 fBranchName.Data(), branchActualType->GetName(), fDict->GetName());
705 if (fSetupStatus == kSetupInternalError || fSetupStatus >= 0)
706 fSetupStatus = kSetupMismatch;
707
708 // Update named proxy's dictionary
709 if (!namedProxy->GetContentDict()) {
710 namedProxy->SetContentDict(fDict);
711 }
712
713 // fProxy = 0;
714 // return;
715 }
716 }
717
718 SetImpl(branch, myLeaf);
719}
720
721////////////////////////////////////////////////////////////////////////////////
722/// Determine the branch / leaf and its type; reset fProxy / fSetupStatus on error.
723
727{
728 myLeaf = nullptr;
729 branch = fTreeReader->GetTree()->GetBranch(fBranchName);
730 if (branch)
731 return true;
732
733 if (!fBranchName.Contains(".")) {
735 Error("TTreeReaderArrayBase::GetBranchAndLeaf()",
736 "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.",
737 fBranchName.Data());
738 }
739 fSetupStatus = kSetupMissingBranch;
740 fProxy = nullptr;
741 return false;
742 }
743
744 TRegexp leafNameExpression("\\.[a-zA-Z0-9_]+$");
745 TString leafName(fBranchName(leafNameExpression));
746 TString branchName = fBranchName(0, fBranchName.Length() - leafName.Length());
747 branch = fTreeReader->GetTree()->GetBranch(branchName);
748 if (!branch) {
750 Error("TTreeReaderArrayBase::GetBranchAndLeaf()",
751 "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.",
752 fBranchName.Data());
753 }
754 fSetupStatus = kSetupMissingBranch;
755 fProxy = nullptr;
756 return false;
757 }
758
759 myLeaf = branch->GetLeaf(TString(leafName(1, leafName.Length())));
760 if (!myLeaf) {
762 Error("TTreeReaderArrayBase::GetBranchAndLeaf()",
763 "The tree does not have a branch, nor a sub-branch called %s. You could check with TTree::Print() for "
764 "available branches.",
765 fBranchName.Data());
766 }
767 fSetupStatus = kSetupMissingBranch;
768 fProxy = nullptr;
769 return false;
770 }
771
773 if (!tempDict) {
774 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Failed to get the dictionary for %s.", myLeaf->GetTypeName());
775 fSetupStatus = kSetupMissingDictionary;
776 fProxy = nullptr;
777 return false;
778 }
779
780 if (tempDict->IsA() == TDataType::Class() &&
781 TDictionary::GetDictionary(((TDataType *)tempDict)->GetTypeName()) == fDict) {
782 // fLeafOffset = myLeaf->GetOffset() / 4;
783 branchActualType = fDict;
784 fLeaf = myLeaf;
785 fBranchName = branchName;
786 fLeafName = leafName(1, leafName.Length());
787 fHaveLeaf = (fLeafName.Length() > 0);
788 fSetupStatus = kSetupMatchLeaf;
789 } else {
790 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Leaf of type %s cannot be read by TTreeReaderValue<%s>.",
791 myLeaf->GetTypeName(), fDict->GetName());
792 fProxy = nullptr;
793 fSetupStatus = kSetupMismatch;
794 return false;
795 }
796 return true;
797}
798
799////////////////////////////////////////////////////////////////////////////////
800/// Create the TVirtualCollectionReader object for our branch.
801
803{
804 if (fImpl)
805 return;
806
807 // Access a branch's collection content (not the collection itself)
808 // through a proxy.
809 // Search for the branchname, determine what it contains, and wire the
810 // TBranchProxy representing it to us so we can access its data.
811 // A proxy for branch must not have been created before (i.e. check
812 // fProxies before calling this function!)
813
814 if (myLeaf) {
815 if (!myLeaf->GetLeafCount()) {
816 fImpl = std::make_unique<TLeafReader>(this);
817 } else {
818 TString leafFullName = myLeaf->GetBranch()->GetName();
819 leafFullName += ".";
820 leafFullName += myLeaf->GetLeafCount()->GetName();
821 fImpl = std::make_unique<TLeafParameterSizeReader>(fTreeReader, leafFullName.Data(), this);
822 }
823 fSetupStatus = kSetupMatchLeaf;
824 } else if (branch->IsA() == TBranchElement::Class()) {
826
828 Int_t id = branchElement->GetID();
829
830 if (id >= 0) { // Not root node?
831 // Int_t offset = streamerInfo->GetOffsets()[id];
832 TStreamerElement *element = (TStreamerElement *)streamerInfo->GetElements()->At(id);
833 // bool isPointer = element->IsaPointer();
834 // TClass *classPointer = element->GetClassPointer();
835
836 if (fSetupStatus == kSetupInternalError)
837 fSetupStatus = kSetupMatch;
838 if (element->IsA() == TStreamerSTL::Class()) {
839 if (branchElement->GetType() == 31) {
840 Error("TTreeReaderArrayBase::SetImpl", "STL Collection nested in a TClonesArray not yet supported");
841 fSetupStatus = kSetupInternalError;
842 return;
843 }
844 fImpl = std::make_unique<TSTLReader>();
845 } else if (element->IsA() == TStreamerObject::Class()) {
846 // fImpl = new TObjectArrayReader(); // BArray[12]
847
848 if (element->GetClass() == TClonesArray::Class()) {
849 fImpl = std::make_unique<TClonesReader>();
850 } else if (branchElement->GetType() == TBranchElement::kSTLMemberNode) {
851 fImpl = std::make_unique<TBasicTypeArrayReader>();
852 } else if (branchElement->GetType() == TBranchElement::kClonesMemberNode) {
853 // TBasicTypeClonesReader should work for object
854 fImpl = std::make_unique<TBasicTypeClonesReader>(element->GetOffset());
855 } else {
856 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
857 }
858 } else if (element->IsA() == TStreamerLoop::Class()) {
859 fImpl =
860 std::make_unique<TArrayParameterSizeReader>(fTreeReader, branchElement->GetBranchCount()->GetName());
861 } else if (element->IsA() == TStreamerBasicType::Class()) {
863 fImpl = std::make_unique<TBasicTypeArrayReader>();
864 } else if (branchElement->GetType() == TBranchElement::kClonesMemberNode) {
865 fImpl = std::make_unique<TBasicTypeClonesReader>(element->GetOffset());
866 } else if (fDict->IsA() == TEnum::Class()) {
867 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
868 ((TObjectArrayReader *)fImpl.get())->SetBasicTypeSize(sizeof(Int_t));
869 } else {
870 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
871 ((TObjectArrayReader *)fImpl.get())->SetBasicTypeSize(((TDataType *)fDict)->Size());
872 }
873 } else if (element->IsA() == TStreamerBasicPointer::Class()) {
874 fImpl =
875 std::make_unique<TArrayParameterSizeReader>(fTreeReader, branchElement->GetBranchCount()->GetName());
876 ((TArrayParameterSizeReader *)fImpl.get())->SetBasicTypeSize(((TDataType *)fDict)->Size());
877 } else if (element->IsA() == TStreamerBase::Class()) {
878 fImpl = std::make_unique<TClonesReader>();
879 } else {
880 Error("TTreeReaderArrayBase::SetImpl()", "Cannot read branch %s: unhandled streamer element type %s",
881 fBranchName.Data(), element->IsA()->GetName());
882 fSetupStatus = kSetupInternalError;
883 }
884 } else { // We are at root node?
885 if (branchElement->GetClass()->GetCollectionProxy()) {
886 fImpl = std::make_unique<TCollectionLessSTLReader>(branchElement->GetClass()->GetCollectionProxy());
887 }
888 }
889 } else if (branch->IsA() == TBranch::Class()) {
890 auto topLeaf = branch->GetLeaf(branch->GetName());
891 if (!topLeaf) {
892 Error("TTreeReaderArrayBase::SetImpl", "Failed to get the top leaf from the branch");
893 fSetupStatus = kSetupMissingBranch;
894 return;
895 }
896 // We could have used GetLeafCounter, but it does not work well with Double32_t and Float16_t: ROOT-10149
897 auto sizeLeaf = topLeaf->GetLeafCount();
898 if (fSetupStatus == kSetupInternalError)
899 fSetupStatus = kSetupMatch;
900 if (!sizeLeaf) {
901 fImpl = std::make_unique<TArrayFixedSizeReader>(topLeaf->GetLenStatic());
902 } else {
903 fImpl = std::make_unique<TArrayParameterSizeReader>(fTreeReader, sizeLeaf->GetName());
904 }
905 ((TObjectArrayReader *)fImpl.get())->SetBasicTypeSize(((TDataType *)fDict)->Size());
906 } else if (branch->IsA() == TBranchClones::Class()) {
907 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchClones not implemented");
908 fSetupStatus = kSetupInternalError;
909 } else if (branch->IsA() == TBranchObject::Class()) {
910 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchObject not implemented");
911 fSetupStatus = kSetupInternalError;
912 } else if (branch->IsA() == TBranchSTL::Class()) {
913 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchSTL not implemented");
914 fImpl = std::make_unique<TSTLReader>();
915 fSetupStatus = kSetupInternalError;
916 } else if (branch->IsA() == TBranchRef::Class()) {
917 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchRef not implemented");
918 fSetupStatus = kSetupInternalError;
919 }
920}
921
922////////////////////////////////////////////////////////////////////////////////
923/// Access a branch's collection content (not the collection itself)
924/// through a proxy.
925/// Retrieve the type of data contained in the collection stored by branch;
926/// put its dictionary into dict, If there is no dictionary, put its type
927/// name into contentTypeName.
928/// The contentTypeName is set to NULL if the branch does not
929/// contain a collection; in that case, the type of the branch is returned.
930/// In all other cases, NULL is returned.
931
933 TDictionary *&dict)
934{
935 dict = nullptr;
936 contentTypeName = "";
937 if (branch->IsA() == TBranchElement::Class()) {
939 if (brElement->GetType() == 4 || brElement->GetType() == 3) {
940 TVirtualCollectionProxy *collProxy = brElement->GetCollectionProxy();
941 if (collProxy) {
942 TClass *myClass = collProxy->GetValueClass();
943 if (!myClass) {
944 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Could not get value class.");
945 return nullptr;
946 }
947 dict = TDictionary::GetDictionary(myClass->GetName());
948 if (!dict)
949 dict = TDataType::GetDataType(collProxy->GetType());
950 }
951 if (!dict) {
952 // We don't know the dictionary, thus we need the content's type name.
953 // Determine it.
954 if (brElement->GetType() == 3) {
955 contentTypeName = brElement->GetClonesName();
956 dict = TDictionary::GetDictionary(brElement->GetClonesName());
957 return nullptr;
958 }
959 // STL:
961 int isSTLCont = splitType.IsSTLCont();
962 if (!isSTLCont) {
963 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
964 "Cannot determine STL collection type of %s stored in branch %s", brElement->GetClassName(),
965 branch->GetName());
966 return brElement->GetClassName();
967 }
969 if (isMap)
970 contentTypeName = "std::pair< ";
971 contentTypeName += splitType.fElements[1];
972 if (isMap) {
973 contentTypeName += splitType.fElements[2];
974 contentTypeName += " >";
975 }
976 return nullptr;
977 }
978 return nullptr;
979 } else if (brElement->GetType() == 31 || brElement->GetType() == 41) {
980 // it's a member, extract from GetClass()'s streamer info
981 TClass *clData = nullptr;
983 int ExpectedTypeRet = brElement->GetExpectedType(clData, dtData);
984 if (ExpectedTypeRet == 0) {
985 dict = clData;
986 if (!dict) {
987 if (dtData == kFloat16_t) {
989 }
990 if (dtData == kDouble32_t) {
992 }
994 }
995 if (!dict) {
996 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
997 "The branch %s contains a data type %d for which the dictionary cannot be retrieved.",
998 branch->GetName(), (int)dtData);
1000 return nullptr;
1001 }
1002 return nullptr;
1003 } else if (ExpectedTypeRet == 1) {
1004 int brID = brElement->GetID();
1005 if (brID == -1) {
1006 // top
1007 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
1008 "The branch %s contains data of type %s for which the dictionary does not exist. It's needed.",
1009 branch->GetName(), brElement->GetClassName());
1010 contentTypeName = brElement->GetClassName();
1011 return nullptr;
1012 }
1013 // Either the data type name doesn't have an EDataType entry
1014 // or the streamer info doesn't have a TClass* attached.
1015 TStreamerElement *element = (TStreamerElement *)brElement->GetInfo()->GetElement(brID);
1016 contentTypeName = element->GetTypeName();
1017 return nullptr;
1018 }
1019 /* else (ExpectedTypeRet == 2)*/
1020 // The streamer info entry cannot be found.
1021 // TBranchElement::GetExpectedType() has already complained.
1022 return "{CANNOT DETERMINE TBranchElement DATA TYPE}";
1023 } else if (brElement->GetType() == TBranchElement::kLeafNode) {
1024 TStreamerInfo *streamerInfo = brElement->GetInfo();
1025 Int_t id = brElement->GetID();
1026
1027 if (id >= 0) {
1028 TStreamerElement *element = (TStreamerElement *)streamerInfo->GetElements()->At(id);
1029
1030 if (element->IsA() == TStreamerSTL::Class()) {
1031 TClass *myClass = brElement->GetCurrentClass();
1032 if (!myClass) {
1033 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get class from branch element.");
1034 return nullptr;
1035 }
1036 TVirtualCollectionProxy *myCollectionProxy = myClass->GetCollectionProxy();
1037 if (!myCollectionProxy) {
1038 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get collection proxy from STL class");
1039 return nullptr;
1040 }
1041 // Try getting the contained class
1042 dict = myCollectionProxy->GetValueClass();
1043 // If it fails, try to get the contained type as a primitive type
1044 if (!dict)
1045 dict = TDataType::GetDataType(myCollectionProxy->GetType());
1046 if (!dict) {
1047 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get valueClass from collectionProxy.");
1048 return nullptr;
1049 }
1050 contentTypeName = dict->GetName();
1051 return nullptr;
1052 } else if (element->IsA() == TStreamerObject::Class() && !strcmp(element->GetTypeName(), "TClonesArray")) {
1053 if (!fProxy->Setup() || !fProxy->Read()) {
1054 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
1055 "Failed to get type from proxy, unable to check type");
1056 contentTypeName = "UNKNOWN";
1057 dict = nullptr;
1058 return contentTypeName;
1059 }
1060 TClonesArray *myArray = (TClonesArray *)fProxy->GetWhere();
1061 dict = myArray->GetClass();
1062 contentTypeName = dict->GetName();
1063 return nullptr;
1064 } else {
1065 dict = brElement->GetCurrentClass();
1066 if (!dict) {
1068 dict = TDataType::GetDataType((EDataType)((TDataType *)myDataType)->GetType());
1069 }
1070 contentTypeName = brElement->GetTypeName();
1071 return nullptr;
1072 }
1073 }
1074 if (brElement->GetCurrentClass() == TClonesArray::Class()) {
1075 contentTypeName = "TClonesArray";
1076 Warning("TTreeReaderArrayBase::GetBranchContentDataType()",
1077 "Not able to check type correctness, ignoring check");
1078 dict = fDict;
1079 fSetupStatus = kSetupNoCheck;
1080 } else if (!dict && (branch->GetSplitLevel() == 0 || brElement->GetClass()->GetCollectionProxy())) {
1081 // Try getting the contained class
1082 dict = brElement->GetClass()->GetCollectionProxy()->GetValueClass();
1083 // If it fails, try to get the contained type as a primitive type
1084 if (!dict)
1085 dict = TDataType::GetDataType(brElement->GetClass()->GetCollectionProxy()->GetType());
1086 if (dict)
1087 contentTypeName = dict->GetName();
1088 return nullptr;
1089 } else if (!dict) {
1090 dict = brElement->GetClass();
1091 contentTypeName = dict->GetName();
1092 return nullptr;
1093 }
1094
1095 return nullptr;
1096 }
1097 return nullptr;
1098 } else if (branch->IsA() == TBranch::Class() || branch->IsA() == TBranchObject::Class() ||
1099 branch->IsA() == TBranchSTL::Class()) {
1100 const char *dataTypeName = branch->GetClassName();
1101 if ((!dataTypeName || !dataTypeName[0]) && branch->IsA() == TBranch::Class()) {
1102 auto myLeaf = branch->GetLeaf(branch->GetName());
1103 if (myLeaf) {
1104 auto myDataType = TDictionary::GetDictionary(myLeaf->GetTypeName());
1105 if (myDataType && myDataType->IsA() == TDataType::Class()) {
1106 auto typeEnumConstant = EDataType(((TDataType *)myDataType)->GetType());
1107 // We need to consider Double32_t and Float16_t as dounle and float respectively
1108 // since this is the type the user uses to instantiate the TTreeReaderArray template.
1111 else if (typeEnumConstant == kFloat16_t)
1114 contentTypeName = myLeaf->GetTypeName();
1115 return nullptr;
1116 }
1117 }
1118
1119 // leaflist. Can't represent.
1120 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
1121 "The branch %s was created using a leaf list and cannot be represented as a C++ type. Please access one "
1122 "of its siblings using a TTreeReaderArray:",
1123 branch->GetName());
1124 TIter iLeaves(branch->GetListOfLeaves());
1125 TLeaf *leaf = nullptr;
1126 while ((leaf = (TLeaf *)iLeaves())) {
1127 Error("TTreeReaderArrayBase::GetBranchContentDataType()", " %s.%s", branch->GetName(), leaf->GetName());
1128 }
1129 return nullptr;
1130 }
1131 if (dataTypeName)
1133 if (branch->IsA() == TBranchSTL::Class()) {
1134 Warning("TTreeReaderArrayBase::GetBranchContentDataType()",
1135 "Not able to check type correctness, ignoring check");
1136 dict = fDict;
1137 fSetupStatus = kSetupNoCheck;
1138 return nullptr;
1139 }
1140 return dataTypeName;
1141 } else if (branch->IsA() == TBranchClones::Class()) {
1142 dict = TClonesArray::Class();
1143 return "TClonesArray";
1144 } else if (branch->IsA() == TBranchRef::Class()) {
1145 // Can't represent.
1146 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
1147 "The branch %s is a TBranchRef and cannot be represented as a C++ type.", branch->GetName());
1148 return nullptr;
1149 } else {
1150 Error("TTreeReaderArrayBase::GetBranchContentDataType()",
1151 "The branch %s is of type %s - something that is not handled yet.", branch->GetName(),
1152 branch->IsA()->GetName());
1153 return nullptr;
1154 }
1155
1156 return nullptr;
1157}
dim_t fSize
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
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
Binding & operator=(OUT(*fun)(void))
Base class for all the proxy object.
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:138
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