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 TUIntOrIntReader: public BASE {
201 private:
202 // The index can be of type int or unsigned int.
203 std::unique_ptr<TTreeReaderValueBase> fSizeReader;
204 bool fIsUnsigned = false;
205
206 protected:
207 template <class T>
208 TTreeReaderValue<T>& GetSizeReader() {
209 return *static_cast<TTreeReaderValue<T>*>(fSizeReader.get());
210 }
211
212 public:
213 template <class... ARGS>
214 TUIntOrIntReader(TTreeReader *treeReader, const char *leafName,
215 ARGS&&... args):
216 BASE(std::forward<ARGS>(args)...)
217 {
218 std::string foundLeafName = leafName;
219 TLeaf* sizeLeaf = treeReader->GetTree()->FindLeaf(foundLeafName.c_str());
220
221 if (!sizeLeaf) {
222 // leafName might be "top.currentParent.N". But "N" might really be "top.N"!
223 // Strip parents until we find the leaf.
224 std::string leafNameNoParent = leafName;
225 std::string parent;
226 auto posLastDot = leafNameNoParent.rfind('.');
227 if (posLastDot != leafNameNoParent.npos) {
228 parent = leafNameNoParent.substr(0, posLastDot);
229 leafNameNoParent.erase(0, posLastDot + 1);
230 }
231
232 do {
233 if (!sizeLeaf && !parent.empty()) {
234 auto posLastDotParent = parent.rfind('.');
235 if (posLastDotParent != parent.npos)
236 parent = parent.substr(0, posLastDot);
237 else
238 parent.clear();
239 }
240
241 foundLeafName = parent;
242 if (!parent.empty())
243 foundLeafName += ".";
244 foundLeafName += leafNameNoParent;
245 sizeLeaf = treeReader->GetTree()->FindLeaf(foundLeafName.c_str());
246 } while (!sizeLeaf && !parent.empty());
247 }
248
249 if (!sizeLeaf) {
250 Error("TUIntOrIntReader", "Cannot find leaf count for %s or any parent branch!", leafName);
251 return;
252 }
253
254 fIsUnsigned = sizeLeaf->IsUnsigned();
255 if (fIsUnsigned) {
256 fSizeReader.reset(new TTreeReaderValue<UInt_t>(*treeReader, foundLeafName.c_str()));
257 } else {
258 fSizeReader.reset(new TTreeReaderValue<Int_t>(*treeReader, foundLeafName.c_str()));
259 }
260 }
261
262 size_t GetSize(ROOT::Detail::TBranchProxy* /*proxy*/) override {
263 if (fIsUnsigned)
264 return *GetSizeReader<UInt_t>();
265 return *GetSizeReader<Int_t>();
266 }
267 };
268
269 class TArrayParameterSizeReader: public TUIntOrIntReader<TObjectArrayReader> {
270 public:
271 TArrayParameterSizeReader(TTreeReader *treeReader, const char *branchName):
272 TUIntOrIntReader<TObjectArrayReader>(treeReader, branchName) {}
273 };
274
275 // Reader interface for fixed size arrays
276 class TArrayFixedSizeReader : public TObjectArrayReader {
277 private:
278 Int_t fSize;
279
280 public:
281 TArrayFixedSizeReader(Int_t sizeArg) : fSize(sizeArg) {}
282
283 virtual size_t GetSize(ROOT::Detail::TBranchProxy* /*proxy*/) { return fSize; }
284 };
285
286 class TBasicTypeArrayReader final: public TVirtualCollectionReader {
287 public:
288 ~TBasicTypeArrayReader() {}
289
291 if (!proxy->Read()){
293 Error("TBasicTypeArrayReader::GetCP()", "Read error in TBranchProxy.");
294 return 0;
295 }
297 return (TVirtualCollectionProxy*) proxy->GetCollection();
298 }
299
300 virtual size_t GetSize(ROOT::Detail::TBranchProxy* proxy){
301 TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
302 if (!myCollectionProxy) return 0;
303 return myCollectionProxy->Size();
304 }
305
306 virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx){
307 TVirtualCollectionProxy *myCollectionProxy = GetCP(proxy);
308 if (!myCollectionProxy) return 0;
309 return (Byte_t*)myCollectionProxy->At(idx) + proxy->GetOffset();
310 }
311 };
312
313 class TBasicTypeClonesReader final: public TClonesReader {
314 private:
315 Int_t fOffset;
316 public:
317 TBasicTypeClonesReader(Int_t offsetArg) : fOffset(offsetArg) {}
318
319 virtual void* At(ROOT::Detail::TBranchProxy* proxy, size_t idx){
320 TClonesArray *myClonesArray = GetCA(proxy);
321 if (!myClonesArray) return 0;
322 return (Byte_t*)myClonesArray->At(idx) + fOffset;
323 }
324 };
325
326 class TLeafReader : public TVirtualCollectionReader {
327 private:
328 TTreeReaderValueBase *fValueReader;
329 Int_t fElementSize;
330 public:
331 TLeafReader(TTreeReaderValueBase *valueReaderArg) : fValueReader(valueReaderArg), fElementSize(-1) {}
332
333 virtual size_t GetSize(ROOT::Detail::TBranchProxy* /*proxy*/){
334 TLeaf *myLeaf = fValueReader->GetLeaf();
335 return myLeaf ? myLeaf->GetLen() : 0; // Error will be printed by GetLeaf
336 }
337
338 virtual void* At(ROOT::Detail::TBranchProxy* /*proxy*/, size_t idx){
339 ProxyRead();
340 void *address = fValueReader->GetAddress();
341 if (fElementSize == -1){
342 TLeaf *myLeaf = fValueReader->GetLeaf();
343 if (!myLeaf) return 0; // Error will be printed by GetLeaf
344 fElementSize = myLeaf->GetLenType();
345 }
346 return (Byte_t*)address + (fElementSize * idx);
347 }
348
349 protected:
350 void ProxyRead(){
351 fValueReader->ProxyRead();
352 }
353 };
354
355 class TLeafParameterSizeReader: public TUIntOrIntReader<TLeafReader> {
356 public:
357 TLeafParameterSizeReader(TTreeReader *treeReader, const char *leafName,
358 TTreeReaderValueBase *valueReaderArg) :
359 TUIntOrIntReader<TLeafReader>(treeReader, leafName, valueReaderArg) {}
360
361 size_t GetSize(ROOT::Detail::TBranchProxy* proxy) override {
362 ProxyRead();
363 return TUIntOrIntReader<TLeafReader>::GetSize(proxy);
364 }
365 };
366}
367
368
369
371
372////////////////////////////////////////////////////////////////////////////////
373/// Create the proxy object for our branch.
374
376{
377 if (fProxy) {
378 return;
379 }
380
381 fSetupStatus = kSetupInternalError; // Fallback; set to something concrete below.
382 if (!fTreeReader) {
383 Error("TTreeReaderArrayBase::CreateProxy()", "TTreeReader object not set / available for branch %s!",
384 fBranchName.Data());
385 fSetupStatus = kSetupTreeDestructed;
386 return;
387 }
388 if (!fDict) {
389 TBranch* br = fTreeReader->GetTree()->GetBranch(fBranchName);
390 const char* brDataType = "{UNDETERMINED}";
391 if (br) {
392 TDictionary* dictUnused = 0;
393 brDataType = GetBranchDataType(br, dictUnused, fDict);
394 }
395 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.",
396 GetDerivedTypeName(), fBranchName.Data(), brDataType);
397 fSetupStatus = kSetupMissingDictionary;
398 return;
399 }
400
401 // Access a branch's collection content (not the collection itself)
402 // through a proxy.
403 // Search for the branchname, determine what it contains, and wire the
404 // TBranchProxy representing it to us so we can access its data.
405
406 TDictionary* branchActualType = 0;
407 TBranch* branch = nullptr;
408 TLeaf *myLeaf = nullptr;
409 if (!GetBranchAndLeaf(branch, myLeaf, branchActualType))
410 return;
411
412 if (!fDict) {
413 Error("TTreeReaderArrayBase::CreateProxy()",
414 "No dictionary for branch %s.", fBranchName.Data());
415 return;
416 }
417
418 TNamedBranchProxy* namedProxy = fTreeReader->FindProxy(fBranchName);
419 if (namedProxy) {
420 if (namedProxy->GetContentDict() == fDict) {
421 fSetupStatus = kSetupMatch;
422 fProxy = namedProxy->GetProxy();
423 SetImpl(branch, myLeaf);
424 return;
425 }
426
427 // Update named proxy's dictionary
428 if (!namedProxy->GetContentDict()) {
429 namedProxy->SetContentDict(fDict);
430 fProxy = namedProxy->GetProxy();
431 if (fProxy)
432 fSetupStatus = kSetupMatch;
433 } else {
434 Error("TTreeReaderArrayBase::CreateProxy()",
435 "Type ambiguity (want %s, have %s) for branch %s.",
436 fDict->GetName(), namedProxy->GetContentDict()->GetName(), fBranchName.Data());
437 }
438 }
439 else {
440 TString membername;
441
442 bool isTopLevel = branch->GetMother() == branch;
443 if (!isTopLevel) {
444 membername = strrchr(branch->GetName(), '.');
445 if (membername.IsNull()) {
446 membername = branch->GetName();
447 }
448 }
449 auto director = fTreeReader->fDirector;
450 // Determine if the branch is actually in a Friend TTree and if so which.
451 if (branch->GetTree() != fTreeReader->GetTree()->GetTree()) {
452 // It is in a friend, let's find the 'index' in the list of friend ...
453 int index = -1;
454 int current = 0;
455 for(auto fe : TRangeDynCast<TFriendElement>( fTreeReader->GetTree()->GetTree()->GetListOfFriends())) {
456 if (branch->GetTree() == fe->GetTree()) {
457 index = current;
458 }
459 ++current;
460 }
461 if (index == -1) {
462 Error("TTreeReaderArrayBase::CreateProxy()", "The branch %s is contained in a Friend TTree that is not directly attached to the main.\n"
463 "This is not yet supported by TTreeReader.",
464 fBranchName.Data());
465 return;
466 }
467 TFriendProxy *feproxy = nullptr;
468 if ((size_t)index < fTreeReader->fFriendProxies.size()) {
469 feproxy = fTreeReader->fFriendProxies.at(index);
470 }
471 if (!feproxy) {
472 feproxy = new ROOT::Internal::TFriendProxy(director, fTreeReader->GetTree(), index);
473 fTreeReader->fFriendProxies.resize(index+1);
474 fTreeReader->fFriendProxies.at(index) = feproxy;
475 }
476 director = feproxy->GetDirector();
477 }
478 namedProxy = new TNamedBranchProxy(director, branch, fBranchName, membername);
479 fTreeReader->AddProxy(namedProxy);
480 fProxy = namedProxy->GetProxy();
481 if (fProxy)
482 fSetupStatus = kSetupMatch;
483 else
484 fSetupStatus = kSetupMismatch;
485 }
486
487 if (!myLeaf){
488 TString branchActualTypeName;
489 const char* nonCollTypeName = GetBranchContentDataType(branch, branchActualTypeName, branchActualType);
490 if (nonCollTypeName) {
491 Error("TTreeReaderArrayBase::CreateContentProxy()", "The branch %s contains data of type %s, which should be accessed through a TTreeReaderValue< %s >.",
492 fBranchName.Data(), nonCollTypeName, nonCollTypeName);
493 if (fSetupStatus == kSetupInternalError)
494 fSetupStatus = kSetupNotACollection;
495 fProxy = 0;
496 return;
497 }
498 if (!branchActualType) {
499 if (branchActualTypeName.IsNull()) {
500 Error("TTreeReaderArrayBase::CreateContentProxy()", "Cannot determine the type contained in the collection of branch %s. That's weird - please report!",
501 fBranchName.Data());
502 } else {
503 Error("TTreeReaderArrayBase::CreateContentProxy()", "The branch %s contains data of type %s, which does not have a dictionary.",
504 fBranchName.Data(), branchActualTypeName.Data());
505 if (fSetupStatus == kSetupInternalError)
506 fSetupStatus = kSetupMissingDictionary;
507 }
508 fProxy = 0;
509 return;
510 }
511
512 auto matchingDataType = [](TDictionary *left, TDictionary *right) -> bool {
513 if (left == right)
514 return true;
515 if (!left || !right)
516 return false;
517 auto left_datatype = dynamic_cast<TDataType *>(left);
518 auto right_datatype = dynamic_cast<TDataType *>(right);
519 if (!left_datatype || !right_datatype)
520 return false;
521 auto l = left_datatype->GetType();
522 auto r = right_datatype->GetType();
523 if ( l > 0 && l == r)
524 return true;
525 else
526 return ( (l == kDouble32_t && r == kDouble_t)
527 || (l == kDouble_t && r == kDouble32_t)
528 || (l == kFloat16_t && r == kFloat_t)
529 || (l == kFloat_t && r == kFloat16_t));
530 };
531
532 if (! matchingDataType(fDict, branchActualType)) {
533 Error("TTreeReaderArrayBase::CreateContentProxy()", "The branch %s contains data of type %s. It cannot be accessed by a TTreeReaderArray<%s>",
534 fBranchName.Data(), branchActualType->GetName(), fDict->GetName());
535 if (fSetupStatus == kSetupInternalError || fSetupStatus >= 0)
536 fSetupStatus = kSetupMismatch;
537
538 // Update named proxy's dictionary
539 if (!namedProxy->GetContentDict()) {
540 namedProxy->SetContentDict(fDict);
541 }
542
543 // fProxy = 0;
544 // return;
545 }
546 }
547
548 SetImpl(branch, myLeaf);
549}
550
551////////////////////////////////////////////////////////////////////////////////
552/// Determine the branch / leaf and its type; reset fProxy / fSetupStatus on error.
553
555 TDictionary* &branchActualType) {
556 myLeaf = nullptr;
557 branch = fTreeReader->GetTree()->GetBranch(fBranchName);
558 if (branch)
559 return true;
560
561 if (!fBranchName.Contains(".")) {
562 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.", fBranchName.Data());
563 fSetupStatus = kSetupMissingBranch;
564 fProxy = 0;
565 return false;
566 }
567
568 TRegexp leafNameExpression ("\\.[a-zA-Z0-9_]+$");
569 TString leafName (fBranchName(leafNameExpression));
570 TString branchName = fBranchName(0, fBranchName.Length() - leafName.Length());
571 branch = fTreeReader->GetTree()->GetBranch(branchName);
572 if (!branch){
573 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "The tree does not have a branch called %s. You could check with TTree::Print() for available branches.", fBranchName.Data());
574 fSetupStatus = kSetupMissingBranch;
575 fProxy = 0;
576 return false;
577 }
578
579 myLeaf = branch->GetLeaf(TString(leafName(1, leafName.Length())));
580 if (!myLeaf){
581 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());
582 fSetupStatus = kSetupMissingBranch;
583 fProxy = 0;
584 return false;
585 }
586
588 if (!tempDict){
589 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Failed to get the dictionary for %s.", myLeaf->GetTypeName());
590 fSetupStatus = kSetupMissingDictionary;
591 fProxy = 0;
592 return false;
593 }
594
595 if (tempDict->IsA() == TDataType::Class() && TDictionary::GetDictionary(((TDataType*)tempDict)->GetTypeName()) == fDict){
596 //fLeafOffset = myLeaf->GetOffset() / 4;
597 branchActualType = fDict;
598 fLeaf = myLeaf;
599 fBranchName = branchName;
600 fLeafName = leafName(1, leafName.Length());
601 fHaveLeaf = (fLeafName.Length() > 0);
602 fSetupStatus = kSetupMatchLeaf;
603 }
604 else {
605 Error("TTreeReaderArrayBase::GetBranchAndLeaf()", "Leaf of type %s cannot be read by TTreeReaderValue<%s>.", myLeaf->GetTypeName(), fDict->GetName());
606 fProxy = 0;
607 fSetupStatus = kSetupMismatch;
608 return false;
609 }
610 return true;
611}
612
613
614
615
616////////////////////////////////////////////////////////////////////////////////
617/// Create the TVirtualCollectionReader object for our branch.
618
620{
621 if (fImpl)
622 return;
623
624 // Access a branch's collection content (not the collection itself)
625 // through a proxy.
626 // Search for the branchname, determine what it contains, and wire the
627 // TBranchProxy representing it to us so we can access its data.
628 // A proxy for branch must not have been created before (i.e. check
629 // fProxies before calling this function!)
630
631 if (myLeaf){
632 if (!myLeaf->GetLeafCount()){
633 fImpl = std::make_unique<TLeafReader>(this);
634 }
635 else {
636 TString leafFullName = myLeaf->GetBranch()->GetName();
637 leafFullName += ".";
638 leafFullName += myLeaf->GetLeafCount()->GetName();
639 fImpl = std::make_unique<TLeafParameterSizeReader>(fTreeReader, leafFullName.Data(), this);
640 }
641 fSetupStatus = kSetupMatchLeaf;
642 }
643 else if (branch->IsA() == TBranchElement::Class()) {
644 TBranchElement* branchElement = ((TBranchElement*)branch);
645
646 TStreamerInfo *streamerInfo = branchElement->GetInfo();
647 Int_t id = branchElement->GetID();
648
649 if (id >= 0){ // Not root node?
650 // Int_t offset = streamerInfo->GetOffsets()[id];
651 TStreamerElement *element = (TStreamerElement*)streamerInfo->GetElements()->At(id);
652 // Bool_t isPointer = element->IsaPointer();
653 // TClass *classPointer = element->GetClassPointer();
654
655 if (fSetupStatus == kSetupInternalError)
656 fSetupStatus = kSetupMatch;
657 if (element->IsA() == TStreamerSTL::Class()){
658 fImpl = std::make_unique<TSTLReader>();
659 }
660 else if (element->IsA() == TStreamerObject::Class()){
661 //fImpl = new TObjectArrayReader(); // BArray[12]
662
663 if (element->GetClass() == TClonesArray::Class()){
664 fImpl = std::make_unique<TClonesReader>();
665 }
666 else if (branchElement->GetType() == TBranchElement::kSTLMemberNode){
667 fImpl = std::make_unique<TBasicTypeArrayReader>();
668 }
669 else if (branchElement->GetType() == TBranchElement::kClonesMemberNode){
670 // TBasicTypeClonesReader should work for object
671 fImpl = std::make_unique<TBasicTypeClonesReader>(element->GetOffset());
672 }
673 else {
674 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
675 }
676 }
677 else if (element->IsA() == TStreamerLoop::Class()) {
678 fImpl = std::make_unique<TArrayParameterSizeReader>(fTreeReader, branchElement->GetBranchCount()->GetName());
679 }
680 else if (element->IsA() == TStreamerBasicType::Class()){
681 if (branchElement->GetType() == TBranchElement::kSTLMemberNode){
682 fImpl = std::make_unique<TBasicTypeArrayReader>();
683 }
684 else if (branchElement->GetType() == TBranchElement::kClonesMemberNode){
685 fImpl = std::make_unique<TBasicTypeClonesReader>(element->GetOffset());
686 }
687 else {
688 fImpl = std::make_unique<TArrayFixedSizeReader>(element->GetArrayLength());
689 ((TObjectArrayReader*)fImpl.get())->SetBasicTypeSize(((TDataType*)fDict)->Size());
690 }
691 }
692 else if (element->IsA() == TStreamerBasicPointer::Class()) {
693 fImpl = std::make_unique<TArrayParameterSizeReader>(fTreeReader, branchElement->GetBranchCount()->GetName());
694 ((TArrayParameterSizeReader*)fImpl.get())->SetBasicTypeSize(((TDataType*)fDict)->Size());
695 }
696 else if (element->IsA() == TStreamerBase::Class()){
697 fImpl = std::make_unique<TClonesReader>();
698 } else {
699 Error("TTreeReaderArrayBase::SetImpl()",
700 "Cannot read branch %s: unhandled streamer element type %s",
701 fBranchName.Data(), element->IsA()->GetName());
702 fSetupStatus = kSetupInternalError;
703 }
704 }
705 else { // We are at root node?
706 if (branchElement->GetClass()->GetCollectionProxy()){
707 fImpl = std::make_unique<TCollectionLessSTLReader>(branchElement->GetClass()->GetCollectionProxy());
708 }
709 }
710 } else if (branch->IsA() == TBranch::Class()) {
711 auto topLeaf = branch->GetLeaf(branch->GetName());
712 if (!topLeaf) {
713 Error("TTreeReaderArrayBase::SetImpl", "Failed to get the top leaf from the branch");
714 fSetupStatus = kSetupMissingBranch;
715 return;
716 }
717 // We could have used GetLeafCounter, but it does not work well with Double32_t and Float16_t: ROOT-10149
718 auto sizeLeaf = topLeaf->GetLeafCount();
719 if (fSetupStatus == kSetupInternalError)
720 fSetupStatus = kSetupMatch;
721 if (!sizeLeaf) {
722 fImpl = std::make_unique<TArrayFixedSizeReader>(topLeaf->GetLenStatic());
723 }
724 else {
725 fImpl = std::make_unique<TArrayParameterSizeReader>(fTreeReader, sizeLeaf->GetName());
726 }
727 ((TObjectArrayReader*)fImpl.get())->SetBasicTypeSize(((TDataType*)fDict)->Size());
728 } else if (branch->IsA() == TBranchClones::Class()) {
729 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchClones not implemented");
730 fSetupStatus = kSetupInternalError;
731 } else if (branch->IsA() == TBranchObject::Class()) {
732 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchObject not implemented");
733 fSetupStatus = kSetupInternalError;
734 } else if (branch->IsA() == TBranchSTL::Class()) {
735 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchSTL not implemented");
736 fImpl = std::make_unique<TSTLReader>();
737 fSetupStatus = kSetupInternalError;
738 } else if (branch->IsA() == TBranchRef::Class()) {
739 Error("TTreeReaderArrayBase::SetImpl", "Support for branches of type TBranchRef not implemented");
740 fSetupStatus = kSetupInternalError;
741 }
742}
743
744////////////////////////////////////////////////////////////////////////////////
745/// Access a branch's collection content (not the collection itself)
746/// through a proxy.
747/// Retrieve the type of data contained in the collection stored by branch;
748/// put its dictionary into dict, If there is no dictionary, put its type
749/// name into contentTypeName.
750/// The contentTypeName is set to NULL if the branch does not
751/// contain a collection; in that case, the type of the branch is returned.
752/// In all other cases, NULL is returned.
753
755 TString& contentTypeName,
756 TDictionary* &dict)
757{
758 dict = nullptr;
759 contentTypeName = "";
760 if (branch->IsA() == TBranchElement::Class()) {
761 TBranchElement* brElement = (TBranchElement*)branch;
762 if (brElement->GetType() == 4
763 || brElement->GetType() == 3) {
764 TVirtualCollectionProxy* collProxy = brElement->GetCollectionProxy();
765 if (collProxy) {
766 TClass *myClass = collProxy->GetValueClass();
767 if (!myClass){
768 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Could not get value class.");
769 return 0;
770 }
771 dict = TDictionary::GetDictionary(myClass->GetName());
772 if (!dict) dict = TDataType::GetDataType(collProxy->GetType());
773 }
774 if (!dict) {
775 // We don't know the dictionary, thus we need the content's type name.
776 // Determine it.
777 if (brElement->GetType() == 3) {
778 contentTypeName = brElement->GetClonesName();
779 dict = TDictionary::GetDictionary(brElement->GetClonesName());
780 return 0;
781 }
782 // STL:
783 TClassEdit::TSplitType splitType(brElement->GetClassName());
784 int isSTLCont = splitType.IsSTLCont();
785 if (!isSTLCont) {
786 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Cannot determine STL collection type of %s stored in branch %s", brElement->GetClassName(), branch->GetName());
787 return brElement->GetClassName();
788 }
789 bool isMap = isSTLCont == ROOT::kSTLmap
790 || isSTLCont == ROOT::kSTLmultimap;
791 if (isMap) contentTypeName = "std::pair< ";
792 contentTypeName += splitType.fElements[1];
793 if (isMap) {
794 contentTypeName += splitType.fElements[2];
795 contentTypeName += " >";
796 }
797 return 0;
798 }
799 return 0;
800 } else if (brElement->GetType() == 31
801 || brElement->GetType() == 41) {
802 // it's a member, extract from GetClass()'s streamer info
803 TClass* clData = 0;
804 EDataType dtData = kOther_t;
805 int ExpectedTypeRet = brElement->GetExpectedType(clData, dtData);
806 if (ExpectedTypeRet == 0) {
807 dict = clData;
808 if (!dict) {
809 if (dtData == kFloat16_t) {
810 dtData = kFloat_t;
811 }
812 if (dtData == kDouble32_t) {
813 dtData = kDouble_t;
814 }
815 dict = TDataType::GetDataType(dtData);
816 }
817 if (!dict) {
818 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s contains a data type %d for which the dictionary cannot be retrieved.",
819 branch->GetName(), (int)dtData);
820 contentTypeName = TDataType::GetTypeName(dtData);
821 return 0;
822 }
823 return 0;
824 } else if (ExpectedTypeRet == 1) {
825 int brID = brElement->GetID();
826 if (brID == -1) {
827 // top
828 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s contains data of type %s for which the dictionary does not exist. It's needed.",
829 branch->GetName(), brElement->GetClassName());
830 contentTypeName = brElement->GetClassName();
831 return 0;
832 }
833 // Either the data type name doesn't have an EDataType entry
834 // or the streamer info doesn't have a TClass* attached.
835 TStreamerElement* element =
836 (TStreamerElement*) brElement->GetInfo()->GetElement(brID);
837 contentTypeName = element->GetTypeName();
838 return 0;
839 }
840 /* else (ExpectedTypeRet == 2)*/
841 // The streamer info entry cannot be found.
842 // TBranchElement::GetExpectedType() has already complained.
843 return "{CANNOT DETERMINE TBranchElement DATA TYPE}";
844 }
845 else if (brElement->GetType() == TBranchElement::kLeafNode){
846 TStreamerInfo *streamerInfo = brElement->GetInfo();
847 Int_t id = brElement->GetID();
848
849 if (id >= 0){
850 TStreamerElement *element = (TStreamerElement*)streamerInfo->GetElements()->At(id);
851
852 if (element->IsA() == TStreamerSTL::Class()){
853 TClass *myClass = brElement->GetCurrentClass();
854 if (!myClass){
855 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get class from branch element.");
856 return 0;
857 }
858 TVirtualCollectionProxy *myCollectionProxy = myClass->GetCollectionProxy();
859 if (!myCollectionProxy){
860 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get collection proxy from STL class");
861 return 0;
862 }
863 // Try getting the contained class
864 dict = myCollectionProxy->GetValueClass();
865 // If it fails, try to get the contained type as a primitive type
866 if (!dict) dict = TDataType::GetDataType(myCollectionProxy->GetType());
867 if (!dict){
868 Error("TTreeReaderArrayBase::GetBranchDataType()", "Could not get valueClass from collectionProxy.");
869 return 0;
870 }
871 contentTypeName = dict->GetName();
872 return 0;
873 }
874 else if (element->IsA() == TStreamerObject::Class() && !strcmp(element->GetTypeName(), "TClonesArray")){
875 if (!fProxy->Setup() || !fProxy->Read()){
876 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "Failed to get type from proxy, unable to check type");
877 contentTypeName = "UNKNOWN";
878 dict = 0;
879 return contentTypeName;
880 }
881 TClonesArray *myArray = (TClonesArray*)fProxy->GetWhere();
882 dict = myArray->GetClass();
883 contentTypeName = dict->GetName();
884 return 0;
885 }
886 else {
887 dict = brElement->GetCurrentClass();
888 if (!dict) {
889 TDictionary *myDataType = TDictionary::GetDictionary(brElement->GetTypeName());
890 dict = TDataType::GetDataType((EDataType)((TDataType*)myDataType)->GetType());
891 }
892 contentTypeName = brElement->GetTypeName();
893 return 0;
894 }
895 }
896 if (brElement->GetCurrentClass() == TClonesArray::Class()){
897 contentTypeName = "TClonesArray";
898 Warning("TTreeReaderArrayBase::GetBranchContentDataType()", "Not able to check type correctness, ignoring check");
899 dict = fDict;
900 fSetupStatus = kSetupNoCheck;
901 }
902 else if (!dict && (branch->GetSplitLevel() == 0 || brElement->GetClass()->GetCollectionProxy())){
903 // Try getting the contained class
904 dict = brElement->GetClass()->GetCollectionProxy()->GetValueClass();
905 // If it fails, try to get the contained type as a primitive type
906 if (!dict) dict = TDataType::GetDataType(brElement->GetClass()->GetCollectionProxy()->GetType());
907 if (dict) contentTypeName = dict->GetName();
908 return 0;
909 }
910 else if (!dict){
911 dict = brElement->GetClass();
912 contentTypeName = dict->GetName();
913 return 0;
914 }
915
916 return 0;
917 }
918 return 0;
919 } else if (branch->IsA() == TBranch::Class()
920 || branch->IsA() == TBranchObject::Class()
921 || branch->IsA() == TBranchSTL::Class()) {
922 const char* dataTypeName = branch->GetClassName();
923 if ((!dataTypeName || !dataTypeName[0])
924 && branch->IsA() == TBranch::Class()) {
925 auto myLeaf = branch->GetLeaf(branch->GetName());
926 if (myLeaf){
927 auto myDataType = TDictionary::GetDictionary(myLeaf->GetTypeName());
928 if (myDataType && myDataType->IsA() == TDataType::Class()){
929 auto typeEnumConstant = EDataType(((TDataType*)myDataType)->GetType());
930 // We need to consider Double32_t and Float16_t as dounle and float respectively
931 // since this is the type the user uses to instantiate the TTreeReaderArray template.
932 if (typeEnumConstant == kDouble32_t) typeEnumConstant = kDouble_t;
933 else if (typeEnumConstant == kFloat16_t) typeEnumConstant = kFloat_t;
934 dict = TDataType::GetDataType(typeEnumConstant);
935 contentTypeName = myLeaf->GetTypeName();
936 return 0;
937 }
938 }
939
940 // leaflist. Can't represent.
941 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());
942 TIter iLeaves(branch->GetListOfLeaves());
943 TLeaf* leaf = 0;
944 while ((leaf = (TLeaf*) iLeaves())) {
945 Error("TTreeReaderArrayBase::GetBranchContentDataType()", " %s.%s", branch->GetName(), leaf->GetName());
946 }
947 return 0;
948 }
949 if (dataTypeName) dict = TDictionary::GetDictionary(dataTypeName);
950 if (branch->IsA() == TBranchSTL::Class()){
951 Warning("TTreeReaderArrayBase::GetBranchContentDataType()", "Not able to check type correctness, ignoring check");
952 dict = fDict;
953 fSetupStatus = kSetupNoCheck;
954 return 0;
955 }
956 return dataTypeName;
957 } else if (branch->IsA() == TBranchClones::Class()) {
958 dict = TClonesArray::Class();
959 return "TClonesArray";
960 } else if (branch->IsA() == TBranchRef::Class()) {
961 // Can't represent.
962 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s is a TBranchRef and cannot be represented as a C++ type.", branch->GetName());
963 return 0;
964 } else {
965 Error("TTreeReaderArrayBase::GetBranchContentDataType()", "The branch %s is of type %s - something that is not handled yet.", branch->GetName(), branch->IsA()->GetName());
966 return 0;
967 }
968
969 return 0;
970}
size_t fSize
ROOT::R::TRInterface & r
Definition Object.C:4
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:364
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:187
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:231
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.
A Branch for the case of an object.
TBranchElement * GetBranchCount() const
Int_t GetID() const
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
virtual Int_t GetExpectedType(TClass *&clptr, EDataType &type)
Fill expectedClass and expectedType with information on the data type of the object/values contained ...
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
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:1993
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
Int_t GetSplitLevel() const
Definition TBranch.h:246
TObjArray * GetListOfLeaves()
Definition TBranch.h:243
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition TBranch.cxx:2065
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:80
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2895
Int_t GetClassSize() const
Definition TClass.h:422
An array of clone (identical) objects.
TClass * GetClass() const
Basic data type descriptor (datatype information is obtained from CINT).
Definition TDataType.h:44
Int_t GetType() const
Definition TDataType.h:68
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".
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
virtual Bool_t IsUnsigned() const
Definition TLeaf.h:150
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Int_t GetEntries() const
Return the number of objects in array (i.e.
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
TObject * At(Int_t idx) const
Definition TObjArray.h:164
Regular expression class.
Definition TRegexp.h:31
Int_t GetArrayLength() const
const char * GetTypeName() const
TClass * GetClass() const
Int_t GetOffset() const
Describes a persistent version of a class.
TObjArray * GetElements() const
TStreamerElement * GetElement(Int_t id) const
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
const char * Data() const
Definition TString.h:369
Bool_t IsNull() const
Definition TString.h:407
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:5279
virtual TTree * GetTree() const
Definition TTree.h:514
virtual TLeaf * FindLeaf(const char *name)
Find leaf..
Definition TTree.cxx:4904
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
auto * l
Definition textangle.C:4
#define ARGS(alist)
Definition gifencode.c:10