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