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