Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:15:23

0001 // @(#)root/treeplayer:$Id$
0002 // Author: Philippe Canal 01/06/2004
0003 
0004 /*************************************************************************
0005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers and al.        *
0006  * All rights reserved.                                                  *
0007  *                                                                       *
0008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0010  *************************************************************************/
0011 
0012 #ifndef ROOT_TBranchProxy
0013 #define ROOT_TBranchProxy
0014 
0015 #include "TBranchProxyDirector.h"
0016 #include "TTree.h"
0017 #include "TBranchElement.h"
0018 #include "TLeaf.h"
0019 #include "TClonesArray.h"
0020 #include "TString.h"
0021 #include "TError.h"
0022 #include "TVirtualCollectionProxy.h"
0023 #include "TNotifyLink.h"
0024 
0025 #include <algorithm>
0026 #include <string>
0027 #include <iostream>
0028 
0029 class TBranch;
0030 class TStreamerElement;
0031 
0032 // Note we could protect the arrays more by introducing a class TArrayWrapper<class T> which somehow knows
0033 // its internal dimensions and check for them ...
0034 // template <class T> TArrayWrapper {
0035 // public:
0036 //    TArrayWrapper(void *where, int dim1);
0037 //    const T operator[](int i) {
0038 //       if (i>=dim1) return 0;
0039 //       return where[i];
0040 //    };
0041 // };
0042 // 2D array would actually be a wrapper of a wrapper i.e. has a method TArrayWrapper<T> operator[](int i);
0043 
0044 namespace ROOT {
0045 namespace Internal {
0046    ////////////////////////////////////////////////////////////////////////////////
0047    /// String builder to be used in the constructors.
0048    class TBranchProxyHelper {
0049    public:
0050       TString fName;
0051       TBranchProxyHelper(const char *left, const char *right = nullptr) :
0052          fName() {
0053          if (left) {
0054             fName = left;
0055             if (left[0]&&right && fName[fName.Length()-1]!='.') fName += ".";
0056          }
0057          if (right) {
0058             fName += right;
0059          }
0060       }
0061       operator const char*() { return fName.Data(); }
0062    };
0063 
0064    class TTreeReaderValueBase;
0065 } // namespace Internal
0066 
0067 // prevent access violation when executing the df017_vecOpsHEP.C tutorial with ROOT built in release mode
0068 // TODO: to be reviewed when updating Visual Studio or LLVM
0069 #if defined(_MSC_VER) && !defined(__clang__)
0070 #pragma optimize("", off)
0071 #endif
0072 
0073 namespace Detail {
0074    class TBranchProxy {
0075    protected:
0076       Internal::TBranchProxyDirector *fDirector; // contain pointer to TTree and entry to be read
0077 
0078       bool          fInitialized : 1;
0079       const bool    fIsMember : 1;    // true if we proxy an unsplit data member
0080       bool          fIsClone : 1;     // true if we proxy the inside of a TClonesArray
0081       bool          fIsaPointer : 1;  // true if we proxy a data member of pointer type
0082       bool          fHasLeafCount : 1;// true if we proxy a variable size leaf of a leaflist
0083       bool fSuppressMissingBranchError{false}; // Suppress error issued when the branch is missing from the tree
0084 
0085       const TString fBranchName;  // name of the branch to read
0086       TBranchProxy *fParent;      // Proxy to a parent object
0087 
0088       const TString fDataMember;  // name of the (eventual) data member being proxied
0089 
0090 
0091       TString           fClassName;     // class name of the object pointed to by the branch
0092       TClass           *fClass;         // class name of the object pointed to by the branch
0093       TStreamerElement *fElement;
0094       Int_t             fMemberOffset;
0095       Int_t             fOffset;        // Offset inside the object
0096       Int_t             fArrayLength;   // Number of element if the data is an array
0097 
0098       TBranch *fBranch;       // branch to read
0099       union {
0100          TBranchElement *fBranchCount;  // eventual auxiliary branch (for example holding the size)
0101          TLeaf          *fLeafCount;    // eventual auxiliary leaf (for example holding the size)
0102       };
0103 
0104       TNotifyLink<TBranchProxy> fNotify; // Callback object used by the TChain to update this proxy
0105 
0106       Long64_t fRead;     // Last entry read
0107 
0108       void    *fWhere;    // memory location of the data
0109       TVirtualCollectionProxy *fCollection; // Handle to the collection containing the data chunk.
0110 
0111       std::size_t fValueSize{}; // Size of the data type of the proxied branch.
0112 
0113    public:
0114       virtual void Print();
0115 
0116       TBranchProxy();
0117       TBranchProxy(Internal::TBranchProxyDirector* boss, const char* top, const char* name = nullptr);
0118       TBranchProxy(Internal::TBranchProxyDirector* boss, const char *top, const char *name, const char *membername);
0119       TBranchProxy(Internal::TBranchProxyDirector* boss, TBranchProxy *parent, const char* membername, const char* top = nullptr, const char* name = nullptr);
0120       TBranchProxy(Internal::TBranchProxyDirector* boss, TBranch* branch, const char* membername);
0121       TBranchProxy(Internal::TBranchProxyDirector *boss, const char *branchname, TBranch *branch,
0122                    const char *membername, bool suppressMissingBranchError = false);
0123       virtual ~TBranchProxy();
0124 
0125       TBranchProxy* GetProxy() { return this; }
0126       const char* GetBranchName() const { return fBranchName; }
0127 
0128       void Reset();
0129 
0130       bool Notify() {
0131          fRead = -1;
0132          return Setup();
0133       }
0134 
0135       bool Setup();
0136 
0137       bool IsInitialized() {
0138          return fInitialized;
0139          // return fLastTree && fCurrentTreeNumber == fDirector->GetTree()->GetTreeNumber() && fLastTree == fDirector->GetTree();
0140       }
0141 
0142       bool IsaPointer() const {
0143          return fIsaPointer;
0144       }
0145 
0146       bool Read() {
0147          if (R__unlikely(fDirector == nullptr)) return false;
0148 
0149          auto treeEntry = fDirector->GetReadEntry();
0150          if (treeEntry != fRead) {
0151             if (!IsInitialized()) {
0152                if (!Setup()) {
0153                   ::Error("TBranchProxy::Read","%s",Form("Unable to initialize %s\n",fBranchName.Data()));
0154                   return false;
0155                }
0156             }
0157             bool result = true;
0158             if (fParent) {
0159                result = fParent->Read();
0160             } else {
0161                if (fHasLeafCount) {
0162                   if (fBranch != fLeafCount->GetBranch())
0163                      result &= (-1 != fLeafCount->GetBranch()->GetEntry(treeEntry));
0164                } else if (fBranchCount) {
0165                   result &= (-1 != fBranchCount->GetEntry(treeEntry));
0166                }
0167                // Sometimes the branch might be missing, e.g. when processing multiple
0168                // files but one file of the chain does not have the branch.
0169                if (R__unlikely(fBranch == nullptr))
0170                   return false;
0171                result &= (-1 != fBranch->GetEntry(treeEntry));
0172             }
0173             fRead = treeEntry;
0174             if (R__unlikely(fCollection)) {
0175                fCollection->PopProxy(); // works even if no proxy env object was set.
0176                if (IsaPointer()) {
0177                   fCollection->PushProxy( *(void**)fWhere );
0178                } else {
0179                   fCollection->PushProxy( fWhere );
0180                }
0181             }
0182             return result;
0183          } else {
0184             return IsInitialized();
0185          }
0186       }
0187 
0188 private:
0189       friend class ROOT::Internal::TTreeReaderValueBase;
0190 
0191       enum class EReadType {
0192          kDefault,
0193          kNoDirector,
0194          kReadParentNoCollection,
0195          kReadParentCollectionNoPointer,
0196          kReadParentCollectionPointer,
0197          kReadNoParentNoBranchCountCollectionPointer,
0198          kReadNoParentNoBranchCountCollectionNoPointer,
0199          kReadNoParentNoBranchCountNoCollection,
0200          kReadNoParentBranchCountCollectionPointer,
0201          kReadNoParentBranchCountCollectionNoPointer,
0202          kReadNoParentBranchCountNoCollection
0203       };
0204 
0205       EReadType GetReadType()
0206       {
0207          if (fParent) {
0208             if (!fCollection) {
0209                return EReadType::kReadParentNoCollection;
0210             }
0211             if (IsaPointer()) {
0212                return EReadType::kReadParentCollectionPointer;
0213             }
0214             return EReadType::kReadParentCollectionNoPointer;
0215          }
0216          if (fHasLeafCount) {
0217             return EReadType::kDefault;
0218          }
0219          if (fBranchCount) {
0220             if (fCollection) {
0221                if (IsaPointer()) {
0222                   return EReadType::kReadNoParentBranchCountCollectionPointer;
0223                }
0224                return EReadType::kReadNoParentBranchCountCollectionNoPointer;
0225             }
0226             return EReadType::kReadNoParentBranchCountNoCollection;
0227          }
0228          if (fCollection) {
0229             if (IsaPointer()) {
0230                return EReadType::kReadNoParentNoBranchCountCollectionPointer;
0231             }
0232             return EReadType::kReadNoParentNoBranchCountCollectionNoPointer;
0233          }
0234          return EReadType::kReadNoParentNoBranchCountNoCollection;
0235       }
0236 
0237       bool ReadNoDirector() {
0238          return false;
0239       }
0240 
0241       bool ReadParentNoCollection() {
0242          auto treeEntry = fDirector->GetReadEntry();
0243          if (treeEntry != fRead) {
0244             const bool result = fParent->Read();
0245             fRead = treeEntry;
0246             return result;
0247          } else {
0248             return IsInitialized();
0249          }
0250       }
0251 
0252       bool ReadParentCollectionNoPointer() {
0253          auto treeEntry = fDirector->GetReadEntry();
0254          if (treeEntry != fRead) {
0255             const bool result = fParent->Read();
0256             fRead = treeEntry;
0257             fCollection->PopProxy(); // works even if no proxy env object was set.
0258             fCollection->PushProxy( fWhere );
0259             return result;
0260          } else {
0261             return IsInitialized();
0262          }
0263       }
0264 
0265       bool ReadParentCollectionPointer() {
0266          auto treeEntry = fDirector->GetReadEntry();
0267          if (treeEntry != fRead) {
0268             const bool result = fParent->Read();
0269             fRead = treeEntry;
0270             fCollection->PopProxy(); // works even if no proxy env object was set.
0271             fCollection->PushProxy( *(void**)fWhere );
0272             return result;
0273          } else {
0274             return IsInitialized();
0275          }
0276       }
0277 
0278       bool ReadNoParentNoBranchCountCollectionPointer() {
0279          // Sometimes the branch might be missing, e.g. when processing multiple
0280          // files but one file of the chain does not have the branch.
0281          if (R__unlikely(fBranch == nullptr))
0282             return false;
0283          auto treeEntry = fDirector->GetReadEntry();
0284          if (treeEntry != fRead) {
0285             bool result = (-1 != fBranch->GetEntry(treeEntry));
0286             fRead = treeEntry;
0287             fCollection->PopProxy(); // works even if no proxy env object was set.
0288             fCollection->PushProxy( *(void**)fWhere );
0289             return result;
0290          } else {
0291             return IsInitialized();
0292          }
0293       }
0294 
0295       bool ReadNoParentNoBranchCountCollectionNoPointer() {
0296          // Sometimes the branch might be missing, e.g. when processing multiple
0297          // files but one file of the chain does not have the branch.
0298          if (R__unlikely(fBranch == nullptr))
0299             return false;
0300          auto treeEntry = fDirector->GetReadEntry();
0301          if (treeEntry != fRead) {
0302             bool result = (-1 != fBranch->GetEntry(treeEntry));
0303             fRead = treeEntry;
0304             fCollection->PopProxy(); // works even if no proxy env object was set.
0305             fCollection->PushProxy( fWhere );
0306             return result;
0307          } else {
0308             return IsInitialized();
0309          }
0310       }
0311 
0312       bool ReadNoParentNoBranchCountNoCollection() {
0313          // Sometimes the branch might be missing, e.g. when processing multiple
0314          // files but one file of the chain does not have the branch.
0315          if (R__unlikely(fBranch == nullptr))
0316             return false;
0317          auto treeEntry = fDirector->GetReadEntry();
0318          if (treeEntry != fRead) {
0319             bool result = (-1 != fBranch->GetEntry(treeEntry));
0320             fRead = treeEntry;
0321             return result;
0322          } else {
0323             return IsInitialized();
0324          }
0325       }
0326 
0327       bool ReadNoParentBranchCountCollectionPointer() {
0328          // Sometimes the branch might be missing, e.g. when processing multiple
0329          // files but one file of the chain does not have the branch.
0330          if (R__unlikely(fBranch == nullptr))
0331             return false;
0332          auto treeEntry = fDirector->GetReadEntry();
0333          if (treeEntry != fRead) {
0334             bool result = (-1 != fBranchCount->GetEntry(treeEntry));
0335             result &= (-1 != fBranch->GetEntry(treeEntry));
0336             fRead = treeEntry;
0337             fCollection->PopProxy(); // works even if no proxy env object was set.
0338             fCollection->PushProxy( *(void**)fWhere );
0339             return result;
0340          } else {
0341             return IsInitialized();
0342          }
0343       }
0344 
0345       bool ReadNoParentBranchCountCollectionNoPointer() {
0346          // Sometimes the branch might be missing, e.g. when processing multiple
0347          // files but one file of the chain does not have the branch.
0348          if (R__unlikely(fBranch == nullptr))
0349             return false;
0350          auto treeEntry = fDirector->GetReadEntry();
0351          if (treeEntry != fRead) {
0352             bool result = (-1 != fBranchCount->GetEntry(treeEntry));
0353             result &= (-1 != fBranch->GetEntry(treeEntry));
0354             fRead = treeEntry;
0355             fCollection->PopProxy(); // works even if no proxy env object was set.
0356             fCollection->PushProxy( fWhere );
0357             return result;
0358          } else {
0359             return IsInitialized();
0360          }
0361       }
0362 
0363       bool ReadNoParentBranchCountNoCollection() {
0364          // Sometimes the branch might be missing, e.g. when processing multiple
0365          // files but one file of the chain does not have the branch.
0366          if (R__unlikely(fBranch == nullptr))
0367             return false;
0368          auto treeEntry = fDirector->GetReadEntry();
0369          if (treeEntry != fRead) {
0370             bool result = (-1 != fBranchCount->GetEntry(treeEntry));
0371             result &= (-1 != fBranch->GetEntry(treeEntry));
0372             fRead = treeEntry;
0373             return result;
0374          } else {
0375             return IsInitialized();
0376          }
0377       }
0378 
0379 public:
0380 
0381       bool ReadEntries() {
0382          if (R__unlikely(fDirector == nullptr))
0383             return false;
0384          auto treeEntry = fDirector->GetReadEntry();
0385          if (treeEntry != fRead) {
0386             if (!IsInitialized()) {
0387                if (!Setup()) {
0388                   ::Error("TBranchProxy::ReadEntries","%s",Form("Unable to initialize %s\n",fBranchName.Data()));
0389                   return false;
0390                }
0391             }
0392             if (fParent) fParent->ReadEntries();
0393             else {
0394                if (fBranchCount) {
0395                   fBranchCount->TBranch::GetEntry(treeEntry);
0396                }
0397                // Sometimes the branch might be missing, e.g. when processing multiple
0398                // files but one file of the chain does not have the branch.
0399                if (R__unlikely(fBranch == nullptr))
0400                   return false;
0401                fBranch->TBranch::GetEntry(treeEntry);
0402             }
0403             // NO - we only read the entries, not the contained objects!
0404             // fRead = treeEntry;
0405          }
0406          return IsInitialized();
0407       }
0408 
0409       virtual Int_t GetEntries() {
0410          if (!ReadEntries()) return 0;
0411          if (fHasLeafCount) {
0412             return *(Int_t*)fLeafCount->GetValuePointer();
0413          } else if (fBranchCount) {
0414             return fBranchCount->GetNdata();
0415          } else {
0416             return 1;
0417          }
0418       }
0419 
0420       virtual Int_t GetArrayLength() {
0421          return fArrayLength;
0422       }
0423 
0424       TClass *GetClass() {
0425          if (!fDirector) return nullptr;
0426 
0427          if (fDirector->GetReadEntry() != fRead) {
0428             if (!IsInitialized()) {
0429                if (!Setup()) {
0430                   return nullptr;
0431                }
0432             }
0433          }
0434          return fClass;
0435       }
0436 
0437       void* GetWhere() const { return fWhere; } // intentionally non-virtual
0438 
0439       /// Return the address of the element number i. Returns `nullptr` for non-collections. It assumed that Setip() has
0440       /// been called.
0441       virtual void *GetAddressOfElement(UInt_t /*i*/) {
0442          return nullptr;
0443       }
0444 
0445       TVirtualCollectionProxy *GetCollection() { return fCollection; }
0446 
0447       // protected:
0448       virtual  void *GetStart(UInt_t /*i*/=0) {
0449          // return the address of the start of the object being proxied. Assumes
0450          // that Setup() has been called.
0451 
0452          if (fParent) {
0453             fWhere = ((unsigned char*)fParent->GetStart()) + fMemberOffset;
0454          }
0455          if (IsaPointer()) {
0456             if (fWhere) return *(void**)fWhere;
0457             else return nullptr;
0458          } else {
0459             return fWhere;
0460          }
0461       }
0462 
0463       void *GetClaStart(UInt_t i=0) {
0464          // return the address of the start of the object being proxied. Assumes
0465          // that Setup() has been called.  Assumes the object containing this data
0466          // member is held in TClonesArray.
0467 
0468          char *location;
0469 
0470          if (fIsClone) {
0471 
0472             TClonesArray *tca;
0473             tca = (TClonesArray*)GetStart();
0474 
0475             if (!tca || tca->GetLast()<(Int_t)i) return nullptr;
0476 
0477             location = (char*)tca->At(i);
0478 
0479             return location;
0480 
0481          } else if (fParent) {
0482 
0483             //tcaloc = ((unsigned char*)fParent->GetStart());
0484             location = (char*)fParent->GetClaStart(i);
0485 
0486          } else {
0487 
0488             void *tcaloc;
0489             tcaloc = fWhere;
0490             TClonesArray *tca;
0491             tca = (TClonesArray*)tcaloc;
0492 
0493             if (tca->GetLast()<(Int_t)i) return nullptr;
0494 
0495             location = (char*)tca->At(i);
0496          }
0497 
0498          if (location) location += fOffset;
0499          else return nullptr;
0500 
0501          if (IsaPointer()) {
0502             return *(void**)(location);
0503          } else {
0504             return location;
0505          }
0506 
0507       }
0508 
0509       void *GetStlStart(UInt_t i=0) {
0510          // return the address of the start of the object being proxied. Assumes
0511          // that Setup() has been called.  Assumes the object containing this data
0512          // member is held in STL Collection.
0513 
0514          char *location = nullptr;
0515 
0516          if (fCollection) {
0517 
0518             if (fCollection->Size()<i) return nullptr;
0519 
0520             location = (char*)fCollection->At(i);
0521 
0522             // return location;
0523 
0524          } else if (fParent) {
0525 
0526             //tcaloc = ((unsigned char*)fParent->GetStart());
0527             location = (char*)fParent->GetStlStart(i);
0528 
0529          } else {
0530 
0531             R__ASSERT(0);
0532             //void *tcaloc;
0533             //tcaloc = fWhere;
0534             //TClonesArray *tca;
0535             //tca = (TClonesArray*)tcaloc;
0536 
0537             //if (tca->GetLast()<i) return nullptr;
0538 
0539             //location = (char*)tca->At(i);
0540          }
0541 
0542          if (location) location += fOffset;
0543          else return nullptr;
0544 
0545          if (IsaPointer()) {
0546             return *(void**)(location);
0547          } else {
0548             return location;
0549          }
0550 
0551       }
0552 
0553       Int_t GetOffset() { return fOffset; }
0554 
0555       bool GetSuppressErrorsForMissingBranch() const { return fSuppressMissingBranchError; }
0556 
0557       std::size_t GetValueSize() const { return fValueSize; }
0558    };
0559 } // namespace Detail
0560 
0561 #if defined(_MSC_VER) && !defined(__clang__)
0562 #pragma optimize("", on)
0563 #endif
0564 
0565 namespace Internal {
0566 
0567    ////////////////////////////////////////////////////////////////////////////////
0568    /// Concrete Implementation of the branch proxy around the data members which are array of char
0569    class TArrayCharProxy : public Detail::TBranchProxy {
0570    public:
0571       void Print() override {
0572          TBranchProxy::Print();
0573          std::cout << "fWhere " << fWhere << std::endl;
0574          if (fWhere) std::cout << "value? " << *(unsigned char*)GetStart() << std::endl;
0575       }
0576 
0577       using TBranchProxy::TBranchProxy;
0578       TArrayCharProxy() = default; // work around bug in GCC < 7
0579       ~TArrayCharProxy() override = default;
0580 
0581       void *GetAddressOfElement(UInt_t i) final {
0582          if (!Read()) return nullptr;
0583          unsigned char* str = (unsigned char*)GetStart();
0584          return str + i;
0585       }
0586 
0587       unsigned char At(UInt_t i) {
0588          static unsigned char default_val = {};
0589          if (unsigned char* elAddr = (unsigned char*)GetAddressOfElement(i)) {
0590             // should add out-of bound test
0591             return *elAddr;
0592          }
0593          return default_val;
0594       }
0595 
0596       unsigned char operator [](Int_t i) {
0597          return At(i);
0598       }
0599 
0600       unsigned char operator [](UInt_t i) {
0601          return At(i);
0602       }
0603 
0604       operator const char*() {
0605          if (!Read()) return "";
0606          return (const char*)GetStart();
0607       }
0608 
0609       const char* Data() {
0610          if (!Read()) return "";
0611          return (const char*)GetStart();
0612       }
0613 
0614       const char* c_str() {
0615          if (!Read()) return "";
0616          return (const char*)GetStart();
0617       }
0618 
0619       operator std::string() {
0620          if (!Read()) return "";
0621          return std::string((const char*)GetStart());
0622       }
0623 
0624    };
0625 
0626    ////////////////////////////////////////////////////////////////////////////////
0627    /// Base class for the proxy around object in TClonesArray.
0628    class TClaProxy : public Detail::TBranchProxy {
0629    public:
0630       void Print() override {
0631          TBranchProxy::Print();
0632          std::cout << "fWhere " << fWhere << std::endl;
0633          if (fWhere) {
0634             if (IsaPointer()) {
0635                std::cout << "location " << *(TClonesArray**)fWhere << std::endl;
0636             } else {
0637                std::cout << "location " << fWhere << std::endl;
0638             }
0639          }
0640       }
0641 
0642       using TBranchProxy::TBranchProxy;
0643       TClaProxy() = default; // work around bug in GCC < 7
0644       ~TClaProxy() override = default;
0645 
0646       const TClonesArray* GetPtr() {
0647          if (!Read()) return nullptr;
0648          return (TClonesArray*)GetStart();
0649       }
0650 
0651       Int_t GetEntries() override {
0652          if (!ReadEntries()) return 0;
0653          TClonesArray *arr = (TClonesArray*)GetStart();
0654          if (arr) return arr->GetEntries();
0655          return 0;
0656       }
0657 
0658       void *GetAddressOfElement(UInt_t i) final {
0659          if (!Read()) return nullptr;
0660          if (!fWhere) return nullptr;
0661          return GetClaStart(i);
0662       }
0663 
0664       const TClonesArray* operator->() { return GetPtr(); }
0665 
0666    };
0667 
0668    ////////////////////////////////////////////////////////////////////////////////
0669    /// Base class for the proxy around STL containers.
0670    class TStlProxy : public Detail::TBranchProxy {
0671    public:
0672       void Print() override {
0673          TBranchProxy::Print();
0674          std::cout << "fWhere " << fWhere << std::endl;
0675          if (fWhere) {
0676             if (IsaPointer()) {
0677                std::cout << "location " << *(TClonesArray**)fWhere << std::endl;
0678             } else {
0679                std::cout << "location " << fWhere << std::endl;
0680             }
0681          }
0682       }
0683 
0684       using TBranchProxy::TBranchProxy;
0685       TStlProxy() = default; // work around bug in GCC < 7
0686       ~TStlProxy() override = default;
0687 
0688       TVirtualCollectionProxy* GetPtr() {
0689          if (!Read()) return nullptr;
0690          return GetCollection();
0691       }
0692 
0693       Int_t GetEntries() override {
0694          if (!ReadEntries()) return 0;
0695          return GetPtr()->Size();
0696       }
0697 
0698       void *GetAddressOfElement(UInt_t i) final {
0699          if (!Read()) return nullptr;
0700          if (!fWhere) return nullptr;
0701          return GetStlStart(i);
0702       }
0703 
0704       const TVirtualCollectionProxy* operator->() { return GetPtr(); }
0705 
0706    };
0707 
0708    ////////////////////////////////////////////////////////////////////////////////
0709    /// Template of the proxy around objects.
0710    template <class T>
0711    class TImpProxy : public Detail::TBranchProxy {
0712    public:
0713       void Print() override {
0714          TBranchProxy::Print();
0715          std::cout << "fWhere " << fWhere << std::endl;
0716          if (fWhere) std::cout << "value? " << *(T*)GetStart() << std::endl;
0717       }
0718 
0719       using TBranchProxy::TBranchProxy;
0720       TImpProxy() = default; // work around bug in GCC < 7
0721       ~TImpProxy() override = default;
0722 
0723       operator T() {
0724          if (!Read()) return 0;
0725          return *(T*)GetStart();
0726       }
0727 
0728       // For now explicitly disable copying into the value (i.e. the proxy is read-only).
0729       TImpProxy(T) = delete;
0730       TImpProxy &operator=(T) = delete;
0731 
0732    };
0733 
0734    ////////////////////////////////////////////////////////////////////////////////
0735    /// Helper template to be able to determine and
0736    /// use array dimensions.
0737    template <class T, int d = 0> struct TArrayType {
0738       typedef T type_t;
0739       typedef T array_t[d];
0740       static constexpr int gSize = d;
0741    };
0742    ////////////////////////////////////////////////////////////////////////////////
0743    /// Helper class for proxy around multi dimension array
0744    template <class T> struct TArrayType<T,0> {
0745       typedef T type_t;
0746       typedef T array_t;
0747       static constexpr int gSize = 0;
0748    };
0749    ////////////////////////////////////////////////////////////////////////////////
0750    /// Helper class for proxy around multi dimension array
0751    template <class T, int d> struct TMultiArrayType {
0752       typedef typename T::type_t type_t;
0753       typedef typename T::array_t array_t[d];
0754       static constexpr int gSize = d;
0755    };
0756 
0757    ////////////////////////////////////////////////////////////////////////////////
0758    /// Template for concrete implementation of proxy around array of T
0759    template <class T>
0760    class TArrayProxy : public Detail::TBranchProxy {
0761    public:
0762       using TBranchProxy::TBranchProxy;
0763       TArrayProxy() = default; // work around bug in GCC < 7
0764       ~TArrayProxy() override = default;
0765 
0766       typedef typename T::array_t array_t;
0767       typedef typename T::type_t type_t;
0768 
0769       void Print() override {
0770          TBranchProxy::Print();
0771          std::cout << "fWhere " << GetWhere() << std::endl;
0772          if (GetWhere()) std::cout << "value? " << *(type_t*)GetWhere() << std::endl;
0773       }
0774 
0775       Int_t GetEntries() override {
0776          return T::gSize;
0777       }
0778 
0779       void *GetAddressOfElement(UInt_t i) final {
0780          if (!Read()) return nullptr;
0781          if (array_t *arr = (array_t*)((type_t*)(GetStart())))
0782             return &arr[i];
0783          return nullptr;
0784       }
0785 
0786       const array_t &At(UInt_t i) {
0787          static array_t default_val;
0788          // should add out-of bound test
0789          if (array_t *arr = (array_t*)GetAddressOfElement(i))
0790             return *arr;
0791          return default_val;
0792       }
0793 
0794       const array_t &operator [](Int_t i) { return At(i); }
0795       const array_t &operator [](UInt_t i) { return At(i); }
0796    };
0797 
0798    ////////////////////////////////////////////////////////////////////////////////
0799    /// Template of the Concrete Implementation of the branch proxy around TClonesArray of T
0800    template <class T>
0801    class TClaImpProxy : public TClaProxy {
0802    public:
0803 
0804       // void Print() override {
0805       //    TClaProxy::Print();
0806       // }
0807 
0808       using TClaProxy::TClaProxy;
0809       TClaImpProxy() = default; // work around bug in GCC < 7
0810       ~TClaImpProxy() override = default;
0811 
0812       const T& At(UInt_t i) {
0813          static T default_val;
0814          if (void* addr = GetAddressOfElement(i))
0815             return *(T*)addr;
0816          return default_val;
0817       }
0818 
0819       const T& operator [](Int_t i) { return At(i); }
0820       const T& operator [](UInt_t i) { return At(i); }
0821 
0822       // For now explicitly disable copying into the value (i.e. the proxy is read-only).
0823       TClaImpProxy(T) = delete;
0824       TClaImpProxy &operator=(T) = delete;
0825 
0826    };
0827 
0828    ////////////////////////////////////////////////////////////////////////////////
0829    /// Template of the Concrete Implementation of the branch proxy around an stl container of T
0830    template <class T>
0831    class TStlImpProxy : public TStlProxy {
0832    public:
0833 
0834       // void Print() override {
0835       //    TBranchProxy::Print();
0836       // }
0837 
0838       using TStlProxy::TStlProxy;
0839       TStlImpProxy() = default; // work around bug in GCC < 7
0840       ~TStlImpProxy() override = default;
0841 
0842       const T& At(UInt_t i) {
0843          static T default_val;
0844          if (void* addr = GetAddressOfElement(i))
0845             return *(T*)addr;
0846          return default_val;
0847       }
0848 
0849       const T& operator [](Int_t i) { return At(i); }
0850       const T& operator [](UInt_t i) { return At(i); }
0851 
0852       // For now explicitly disable copying into the value (i.e. the proxy is read-only).
0853       TStlImpProxy(T) = delete;
0854       TStlImpProxy &operator=(T) = delete;
0855 
0856    };
0857 
0858    ////////////////////////////////////////////////////////////////////////////////
0859    /// Template of the Concrete Implementation of the branch proxy around an TClonesArray of array of T
0860    template <class T>
0861    class TClaArrayProxy : public TClaProxy {
0862    public:
0863       typedef typename T::array_t array_t;
0864       typedef typename T::type_t type_t;
0865 
0866       // void Print() override {
0867       //    TClaProxy::Print();
0868       // }
0869 
0870       using TClaProxy::TClaProxy;
0871       TClaArrayProxy() = default; // work around bug in GCC < 7
0872       ~TClaArrayProxy() override = default;
0873 
0874       /* const */  array_t *At(UInt_t i) {
0875          static array_t default_val;
0876          if (array_t* ptr = (array_t*)GetAddressOfElement(i))
0877             return ptr; // no de-ref!
0878 
0879          return &default_val;
0880       }
0881 
0882       /* const */ array_t *operator [](Int_t i) { return At(i); }
0883       /* const */ array_t *operator [](UInt_t i) { return At(i); }
0884    };
0885 
0886 
0887    ////////////////////////////////////////////////////////////////////////////////
0888    /// Template of the Concrete Implementation of the branch proxy around an stl container of array of T
0889    template <class T>
0890    class TStlArrayProxy : public TStlProxy {
0891    public:
0892       typedef typename T::array_t array_t;
0893       typedef typename T::type_t type_t;
0894 
0895       // void Print() override {
0896       //    TBranchProxy::Print();
0897       // }
0898 
0899       using TStlProxy::TStlProxy;
0900       TStlArrayProxy() = default; // work around bug in GCC < 7
0901       ~TStlArrayProxy() override = default;
0902 
0903       /* const */  array_t *At(UInt_t i) {
0904          static array_t default_val;
0905          if (array_t* ptr = (array_t*)GetAddressOfElement(i))
0906             return ptr; // no de-ref!
0907          return &default_val;
0908       }
0909 
0910       /* const */ array_t *operator [](Int_t i) { return At(i); }
0911       /* const */ array_t *operator [](UInt_t i) { return At(i); }
0912    };
0913 
0914    //TImpProxy<TObject> d;
0915    typedef TImpProxy<Double_t>   TDoubleProxy;   // Concrete Implementation of the branch proxy around the data members which are double
0916    typedef TImpProxy<Double32_t> TDouble32Proxy; // Concrete Implementation of the branch proxy around the data members which are double32
0917    typedef TImpProxy<Float_t>    TFloatProxy;    // Concrete Implementation of the branch proxy around the data members which are float
0918    typedef TImpProxy<Float16_t>  TFloat16Proxy;  // Concrete Implementation of the branch proxy around the data members which are float16
0919    typedef TImpProxy<UInt_t>     TUIntProxy;     // Concrete Implementation of the branch proxy around the data members which are unsigned int
0920    typedef TImpProxy<ULong_t>    TULongProxy;    // Concrete Implementation of the branch proxy around the data members which are unsigned long
0921    typedef TImpProxy<ULong64_t>  TULong64Proxy;  // Concrete Implementation of the branch proxy around the data members which are unsigned long long
0922    typedef TImpProxy<UShort_t>   TUShortProxy;   // Concrete Implementation of the branch proxy around the data members which are unsigned short
0923    typedef TImpProxy<UChar_t>    TUCharProxy;    // Concrete Implementation of the branch proxy around the data members which are unsigned char
0924    typedef TImpProxy<Int_t>      TIntProxy;      // Concrete Implementation of the branch proxy around the data members which are int
0925    typedef TImpProxy<Long_t>     TLongProxy;     // Concrete Implementation of the branch proxy around the data members which are long
0926    typedef TImpProxy<Long64_t>   TLong64Proxy;   // Concrete Implementation of the branch proxy around the data members which are long long
0927    typedef TImpProxy<Short_t>    TShortProxy;    // Concrete Implementation of the branch proxy around the data members which are short
0928    typedef TImpProxy<Char_t>     TCharProxy;     // Concrete Implementation of the branch proxy around the data members which are char
0929    typedef TImpProxy<bool>     TBoolProxy;     // Concrete Implementation of the branch proxy around the data members which are bool
0930 
0931    typedef TArrayProxy<TArrayType<Double_t> >   TArrayDoubleProxy;   // Concrete Implementation of the branch proxy around the data members which are array of double
0932    typedef TArrayProxy<TArrayType<Double32_t> > TArrayDouble32Proxy; // Concrete Implementation of the branch proxy around the data members which are array of double32
0933    typedef TArrayProxy<TArrayType<Float_t> >    TArrayFloatProxy;    // Concrete Implementation of the branch proxy around the data members which are array of float
0934    typedef TArrayProxy<TArrayType<Float16_t> >  TArrayFloat16Proxy;  // Concrete Implementation of the branch proxy around the data members which are array of float16
0935    typedef TArrayProxy<TArrayType<UInt_t> >     TArrayUIntProxy;     // Concrete Implementation of the branch proxy around the data members which are array of unsigned int
0936    typedef TArrayProxy<TArrayType<ULong_t> >    TArrayULongProxy;    // Concrete Implementation of the branch proxy around the data members which are array of unsigned long
0937    typedef TArrayProxy<TArrayType<ULong64_t> >  TArrayULong64Proxy;  // Concrete Implementation of the branch proxy around the data members which are array of unsigned long long
0938    typedef TArrayProxy<TArrayType<UShort_t> >   TArrayUShortProxy;   // Concrete Implementation of the branch proxy around the data members which are array of unsigned short
0939    typedef TArrayProxy<TArrayType<UChar_t> >    TArrayUCharProxy;    // Concrete Implementation of the branch proxy around the data members which are array of unsigned char
0940    typedef TArrayProxy<TArrayType<Int_t> >      TArrayIntProxy;      // Concrete Implementation of the branch proxy around the data members which are array of int
0941    typedef TArrayProxy<TArrayType<Long_t> >     TArrayLongProxy;     // Concrete Implementation of the branch proxy around the data members which are array of long
0942    typedef TArrayProxy<TArrayType<Long64_t> >   TArrayLong64Proxy;   // Concrete Implementation of the branch proxy around the data members which are array of long long
0943    typedef TArrayProxy<TArrayType<UShort_t> >   TArrayShortProxy;    // Concrete Implementation of the branch proxy around the data members which are array of short
0944    //specialized ! typedef TArrayProxy<TArrayType<Char_t> >  TArrayCharProxy; // Concrete Implementation of the branch proxy around the data members which are array of char
0945    typedef TArrayProxy<TArrayType<bool> >     TArrayBoolProxy;     // Concrete Implementation of the branch proxy around the data members which are array of bool
0946 
0947    typedef TClaImpProxy<Double_t>   TClaDoubleProxy;   // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are double
0948    typedef TClaImpProxy<Double32_t> TClaDouble32Proxy; // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are double32
0949    typedef TClaImpProxy<Float_t>    TClaFloatProxy;    // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are float
0950    typedef TClaImpProxy<Float16_t>  TClaFloat16Proxy;  // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are float16
0951    typedef TClaImpProxy<UInt_t>     TClaUIntProxy;     // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are unsigned int
0952    typedef TClaImpProxy<ULong_t>    TClaULongProxy;    // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are unsigned long
0953    typedef TClaImpProxy<ULong64_t>  TClaULong64Proxy;  // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are unsigned long long
0954    typedef TClaImpProxy<UShort_t>   TClaUShortProxy;   // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are unsigned short
0955    typedef TClaImpProxy<UChar_t>    TClaUCharProxy;    // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are unsigned char
0956    typedef TClaImpProxy<Int_t>      TClaIntProxy;      // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are int
0957    typedef TClaImpProxy<Long_t>     TClaLongProxy;     // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are long
0958    typedef TClaImpProxy<Long64_t>   TClaLong64Proxy;   // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are long long
0959    typedef TClaImpProxy<Short_t>    TClaShortProxy;    // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are short
0960    typedef TClaImpProxy<Char_t>     TClaCharProxy;     // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are char
0961    typedef TClaImpProxy<bool>     TClaBoolProxy;     // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are bool
0962 
0963    typedef TClaArrayProxy<TArrayType<Double_t> >    TClaArrayDoubleProxy;   // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of double
0964    typedef TClaArrayProxy<TArrayType<Double32_t> >  TClaArrayDouble32Proxy; // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of double32
0965    typedef TClaArrayProxy<TArrayType<Float_t> >     TClaArrayFloatProxy;    // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of float
0966    typedef TClaArrayProxy<TArrayType<Float16_t> >   TClaArrayFloat16Proxy;  // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of float16
0967    typedef TClaArrayProxy<TArrayType<UInt_t> >      TClaArrayUIntProxy;     // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of unsigned int
0968    typedef TClaArrayProxy<TArrayType<ULong_t> >     TClaArrayULongProxy;    // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of unsigned long
0969    typedef TClaArrayProxy<TArrayType<ULong64_t> >   TClaArrayULong64Proxy;  // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of unsigned long long
0970    typedef TClaArrayProxy<TArrayType<UShort_t> >    TClaArrayUShortProxy;   // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of unsigned short
0971    typedef TClaArrayProxy<TArrayType<UChar_t> >     TClaArrayUCharProxy;    // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of unsigned char
0972    typedef TClaArrayProxy<TArrayType<Int_t> >       TClaArrayIntProxy;      // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of int
0973    typedef TClaArrayProxy<TArrayType<Long_t> >      TClaArrayLongProxy;     // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of long
0974    typedef TClaArrayProxy<TArrayType<Long64_t> >    TClaArrayLong64Proxy;   // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of long long
0975    typedef TClaArrayProxy<TArrayType<UShort_t> >    TClaArrayShortProxy;    // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of short
0976    typedef TClaArrayProxy<TArrayType<Char_t> >      TClaArrayCharProxy;     // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of char
0977    typedef TClaArrayProxy<TArrayType<bool> >      TClaArrayBoolProxy;     // Concrete Implementation of the branch proxy around the data members of object in TClonesArray which are array of bool
0978    //specialized ! typedef TClaArrayProxy<TArrayType<Char_t> >  TClaArrayCharProxy;
0979 
0980    typedef TStlImpProxy<Double_t>   TStlDoubleProxy;   // Concrete Implementation of the branch proxy around an stl container of double
0981    typedef TStlImpProxy<Double32_t> TStlDouble32Proxy; // Concrete Implementation of the branch proxy around an stl container of double32
0982    typedef TStlImpProxy<Float_t>    TStlFloatProxy;    // Concrete Implementation of the branch proxy around an stl container of float
0983    typedef TStlImpProxy<Float16_t>  TStlFloat16Proxy;  // Concrete Implementation of the branch proxy around an stl container of float16_t
0984    typedef TStlImpProxy<UInt_t>     TStlUIntProxy;     // Concrete Implementation of the branch proxy around an stl container of unsigned int
0985    typedef TStlImpProxy<ULong_t>    TStlULongProxy;    // Concrete Implementation of the branch proxy around an stl container of unsigned long
0986    typedef TStlImpProxy<ULong64_t>  TStlULong64Proxy;  // Concrete Implementation of the branch proxy around an stl container of unsigned long long
0987    typedef TStlImpProxy<UShort_t>   TStlUShortProxy;   // Concrete Implementation of the branch proxy around an stl container of unsigned short
0988    typedef TStlImpProxy<UChar_t>    TStlUCharProxy;    // Concrete Implementation of the branch proxy around an stl container of unsigned char
0989    typedef TStlImpProxy<Int_t>      TStlIntProxy;      // Concrete Implementation of the branch proxy around an stl container of int
0990    typedef TStlImpProxy<Long_t>     TStlLongProxy;     // Concrete Implementation of the branch proxy around an stl container of long
0991    typedef TStlImpProxy<Long64_t>   TStlLong64Proxy;   // Concrete Implementation of the branch proxy around an stl container of long long
0992    typedef TStlImpProxy<Short_t>    TStlShortProxy;    // Concrete Implementation of the branch proxy around an stl container of short
0993    typedef TStlImpProxy<Char_t>     TStlCharProxy;     // Concrete Implementation of the branch proxy around an stl container of char
0994    typedef TStlImpProxy<bool>     TStlBoolProxy;     // Concrete Implementation of the branch proxy around an stl container of bool
0995 
0996    typedef TStlArrayProxy<TArrayType<Double_t> >    TStlArrayDoubleProxy;   // Concrete Implementation of the branch proxy around an stl container of double
0997    typedef TStlArrayProxy<TArrayType<Double32_t> >  TStlArrayDouble32Proxy; // Concrete Implementation of the branch proxy around an stl container of double32
0998    typedef TStlArrayProxy<TArrayType<Float_t> >     TStlArrayFloatProxy;    // Concrete Implementation of the branch proxy around an stl container of float
0999    typedef TStlArrayProxy<TArrayType<Float16_t> >   TStlArrayFloat16Proxy;  // Concrete Implementation of the branch proxy around an stl container of float16_t
1000    typedef TStlArrayProxy<TArrayType<UInt_t> >      TStlArrayUIntProxy;     // Concrete Implementation of the branch proxy around an stl container of unsigned int
1001    typedef TStlArrayProxy<TArrayType<ULong_t> >     TStlArrayULongProxy;    // Concrete Implementation of the branch proxy around an stl container of unsigned long
1002    typedef TStlArrayProxy<TArrayType<ULong64_t> >   TStlArrayULong64Proxy;  // Concrete Implementation of the branch proxy around an stl contained of unsigned long long
1003    typedef TStlArrayProxy<TArrayType<UShort_t> >    TStlArrayUShortProxy;   // Concrete Implementation of the branch proxy around an stl container of unsigned short
1004    typedef TStlArrayProxy<TArrayType<UChar_t> >     TStlArrayUCharProxy;    // Concrete Implementation of the branch proxy around an stl container of unsigned char
1005    typedef TStlArrayProxy<TArrayType<Int_t> >       TStlArrayIntProxy;      // Concrete Implementation of the branch proxy around an stl container of int
1006    typedef TStlArrayProxy<TArrayType<Long_t> >      TStlArrayLongProxy;     // Concrete Implementation of the branch proxy around an stl container of long
1007    typedef TStlArrayProxy<TArrayType<Long64_t> >    TStlArrayLong64Proxy;   // Concrete Implementation of the branch proxy around an stl container of long long
1008    typedef TStlArrayProxy<TArrayType<UShort_t> >    TStlArrayShortProxy;    // Concrete Implementation of the branch proxy around an stl container of UShort_t
1009    typedef TStlArrayProxy<TArrayType<Char_t> >      TStlArrayCharProxy;     // Concrete Implementation of the branch proxy around an stl container of char
1010    typedef TStlArrayProxy<TArrayType<bool> >      TStlArrayBoolProxy;     // Concrete Implementation of the branch proxy around an stl container of bool
1011 
1012 } // namespace Internal
1013 
1014 // Reasonably backward compatible.
1015 using Detail::TBranchProxy;
1016 
1017 } // namespace ROOT
1018 
1019 #endif
1020