Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/root/TBranchProxy.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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