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