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