// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_rroot_branch_element #define tools_rroot_branch_element #include "branch" #include "stl_vector" #include "info" #include "obj_list" //#define TOOLS_RROOT_BRANCH_ELEMENT_DUMP namespace tools { namespace rroot { class branch_element : public branch { typedef branch parent; public: static const std::string& s_class() { static const std::string s_v("tools::rroot::branch_element"); return s_v; } public: //iro virtual void* cast(const std::string& a_class) const { if(void* p = cmp_cast(this,a_class)) return p; return parent::cast(a_class); } virtual const std::string& s_cls() const {return s_class();} public: static cid id_class() {return branch_element_cid();} virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) {return p;} return parent::cast(a_class); } public: virtual bool stream(buffer& a_buffer) { _clear(); short v; unsigned int s, c; if(!a_buffer.read_version(v,s,c)) return false; //::printf("debug : inlib::branch_element::stream : version %d, count %d\n",v,c); if(!parent::stream(a_buffer)) { m_out << "tools::rroot::branch_element::stream : parent::stream() failed." << std::endl; return false; } if(v<=7) { if(!a_buffer.read(fClassName)) return false; if(!a_buffer.read(fClassVersion)) return false; if(!a_buffer.read(fID)) return false; if(!a_buffer.read(fType)) return false; if(!a_buffer.read(fStreamerType)) return false; } else { //v>=8 if(!a_buffer.read(fClassName)) return false; //::printf("debug : inlib::branch_element::stream : fClassName \"%s\"\n",fClassName.c_str()); std::string fParentName; if(!a_buffer.read(fParentName)) return false; //::printf("debug : inlib::branch_element::stream : fParentName \"%s\"\n",fParentName.c_str()); std::string fCloneName; if(!a_buffer.read(fCloneName)) return false; //::printf("debug : inlib::branch_element::stream : fCloneName \"%s\"\n",fCloneName.c_str()); int dummy_int; if(!a_buffer.read(dummy_int)) return false; //fCheckSum //::printf("debug : inlib::branch_element::stream : fCheckSum %d\n",dummy_int); if(v>=10) { short dummy_short; if(!a_buffer.read(dummy_short)) return false; //fClassVersion //::printf("debug : inlib::branch_element::stream : fClassVersion %d\n",dummy_short); } else { if(!a_buffer.read(dummy_int)) return false; //fClassVersion } if(!a_buffer.read(fID)) return false; //::printf("debug : inlib::branch_element::stream : fID %d\n",fID); if(!a_buffer.read(fType)) return false; //::printf("debug : inlib::branch_element::stream : fType %d\n",fType); if(!a_buffer.read(fStreamerType)) return false; //::printf("debug : inlib::branch_element::stream : fStreamerType %d\n",fStreamerType); if(!a_buffer.read(dummy_int)) return false; //fMaximum //::printf("debug : inlib::branch_element::stream : fMaximum %d\n",dummy_int); //TBranchElement* fBranchCount; ifac::args args; if(!pointer_stream(a_buffer,m_fac,args,fBranchCount,fBranchCount_created)) { m_out << "tools::rroot::branch_element::stream : " << "can't read fBranchCount." << std::endl; return false; } //TBranchElement* fBranchCount2; if(!pointer_stream(a_buffer,m_fac,args,fBranchCount2,fBranchCount2_created)) { m_out << "tools::rroot::branch_element::stream : " << "can't read fBranchCount2." << std::endl; _clear(); return false; } } if(!a_buffer.check_byte_count(s,c,"TBranchElement")) {_clear();return false;} return true; } public: //branch virtual bool read_leaves(ifile& a_file,buffer& a_buffer){ // For k value, see the below commented enum EReadWrite from ROOT-6.12.06 code. static int kInt = 3; static int kDouble = 8; static int kDouble32 = 9; static int kUInt = 13; static int kBits = 15; // In v4-00-01 version 8, it is Long64_t. static int kObject = 61; static int kObjectP = 64; if(fType==3) { // TClonesArray master branch (has only the number of elements). //from v4-00-01 int n; if(!a_buffer.read(n)) return false; /* ROOT-6.12.06 code : if ((n < 0) || (n > fMaximum)) { if (IsMissingCollection()) { n = 0; b.SetBufferOffset(b.Length() - sizeof(n)); } else { Error("ReadLeaves", "Incorrect size read for the container in %s\nThe size read is %d when the maximum is %d\nThe size is reset to 0 for this entry (%lld)", GetName(), n, fMaximum, GetReadEntry()); n = 0; } }*/ //::printf("debug : uuuu : ndata %d\n",n); fNdata = n; //TClonesArray *clones = (TClonesArray*)fObject; //if (!clones) return; //if (clones->IsZombie()) return; //clones->Clear(); //clones->ExpandCreateFast(fNdata); //m_out << "debug : tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName // << " : type " << fType << ", fNdata " << n // << std::endl; return true; } else if(fType==31) { // TClonesArray sub-branch (contains the elements). if(fStreamerType==kObject) { //to read EsbRoot fgd_dig.root. int ndata = fBranchCount->get_ndata(); #ifdef TOOLS_RROOT_BRANCH_ELEMENT_DUMP ::printf("debug : %s : fClassName %s : fID %d : kObject : ndata %d\n",m_name.c_str(),fClassName.c_str(),fID,ndata); #endif streamer_info* _info = a_file.find_streamer_info(fClassName); if(!_info) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read(kObject) : streamer_infos for ref_cls " << fClassName << " not found." << std::endl; return false; } streamer_element* _element = _info->find_streamer_element(fID); if(!_element) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read(kObject) : for ref_cls " << fClassName << ", fID " << fID << " streamer element not found." << std::endl; return false; } //::printf("debug : element type name %s\n",_element->type_name().c_str()); obj_list* _list = 0; if(!m_obj) { _list = new obj_list(m_fac); m_obj = _list; } else { _list = id_cast(*m_obj); if(!_list) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read(kObject) : m_obj is not an obj_list." << std::endl; return false; } } _list->safe_clear(); for(int index=0;indextype_name(),args); if(!_obj) {_list->safe_clear();return false;} if(!_obj->stream(a_buffer)){ m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " kObject : obj stream of class " << sout(_element->type_name()) << " failed at index " << index << " (" << ndata << ")." << std::endl; _list->safe_clear(); return false; } _list->add_object(_obj); //give ownership. } return true; } if(fStreamerType==kObjectP) return true; //from v4-00-01 if(fStreamerType==kDouble32) { int ndata = fBranchCount->get_ndata(); #ifdef TOOLS_RROOT_BRANCH_ELEMENT_DUMP ::printf("debug : %s : fID %d : double32 : ndata %d\n",m_name.c_str(),fID,ndata); #endif stl_vector* vec = 0; if(!m_obj) { vec = new stl_vector; m_obj = vec; } else { vec = id_cast >(*m_obj); if(!vec) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read(kDouble32) : m_obj is not a stl_vector." << std::endl; return false; } } vec->resize(ndata); float afloat; for(int ii=0;iiclear(); return false; } //::printf("debug : zzzz %g\n",afloat); (*vec)[ii] = afloat; } return true; } else if(fStreamerType==kDouble) { int ndata = fBranchCount->get_ndata(); #ifdef TOOLS_RROOT_BRANCH_ELEMENT_DUMP ::printf("debug : %s : fID %d : double : ndata %d\n",m_name.c_str(),fID,ndata); #endif stl_vector* vec = 0; if(!m_obj) { vec = new stl_vector; m_obj = vec; } else { vec = id_cast >(*m_obj); if(!vec) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read(kDouble) : m_obj is not a stl_vector." << std::endl; return false; } } vec->resize(ndata); double* _value = vec_data(*vec); if(!a_buffer.read_fast_array(_value,ndata)) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read_fast_array(double) failed." << std::endl; vec->clear(); return false; } return true; } else if(fStreamerType==kInt) { int ndata = fBranchCount->get_ndata(); #ifdef TOOLS_RROOT_BRANCH_ELEMENT_DUMP ::printf("debug : %s : fID %d : int : ndata %d\n",m_name.c_str(),fID,ndata); #endif stl_vector* vec = 0; if(!m_obj) { vec = new stl_vector; m_obj = vec; } else { vec = id_cast >(*m_obj); if(!vec) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read(kInt) : m_obj is not a stl_vector." << std::endl; return false; } } vec->resize(ndata); int* _value = vec_data(*vec); if(!a_buffer.read_fast_array(_value,ndata)) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read_fast_array(int) failed." << std::endl; vec->clear(); return false; } return true; } else if((fStreamerType==kUInt)||(fStreamerType==kBits)) { int ndata = fBranchCount->get_ndata(); #ifdef TOOLS_RROOT_BRANCH_ELEMENT_DUMP if(fStreamerType==kUInt) ::printf("debug : %s : fID %d : uint : ndata %d\n",m_name.c_str(),fID,ndata); else ::printf("debug : %s : fID %d : bits : ndata %d\n",m_name.c_str(),fID,ndata); #endif stl_vector* vec = 0; if(!m_obj) { vec = new stl_vector; m_obj = vec; } else { vec = id_cast >(*m_obj); if(!vec) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read(kUInt) : m_obj is not a stl_vector." << std::endl; return false; } } vec->resize(ndata); uint32* _value = vec_data(*vec); if(!a_buffer.read_fast_array(_value,ndata)) { m_out << "tools::rroot::branch_element::read_leaves : " << sout(m_name) << " :" << " read_fast_array(uint) failed." << std::endl; vec->clear(); return false; } return true; } else { m_out << "tools::rroot::branch_element::read_leaves :" << " name " << m_name << " ref_cls " << fClassName << " : for type " << fType << ", stream_type " << fStreamerType << " not treated." << std::endl; return false; } /* //m_obj = clones_array(m_fac,true,false); //true = owner of objects. uint32 ndata = 1; float* _value = new float[ndata]; if(!a_buffer.read_fast_array(_value,ndata)) { m_out << "tools::rroot::branch_element::read_leaves : \"" << name() << "\" :" << " read_fast_array failed." << std::endl; return false; } */ //} else if(fType<=2) { //in v5-18-00d } else if(fType==0) { // to read wroot.root of examples/cpp/wroot.cpp. // if(fID>=0) { // // branch in split mode // m_out << "tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName << " :" // << " type 0 with ID " << fID << "." // << std::endl; // return true; // if((fID==-1)|| (fID==1) // for pmx to read LHCb files : ){ //from v4-00-01 //if (fBranchCount) fNdata = (Int_t)fBranchCount->GetValue(0,0); //else fNdata = 1; if(fBranchCount) { fNdata = fBranchCount->get_ndata(); //::printf("debug : branch_element::read_leaves : (fType==0,fID==-1) : fNdata %d\n",fNdata); } else { fNdata = 1; } // read object : bool created = false; if(!m_obj) { ifac::args args; m_obj = m_fac.create(fClassName,args); if(!m_obj) return false; created = true; } if(!m_obj->stream(a_buffer)){ m_out << "tools::rroot::branch_element::read_leaves :" << " name " << sout(m_name) << ", ref_cls " << sout(fClassName) << " :" << " obj stream failed." << std::endl; if(created) {delete m_obj;m_obj = 0;} return false; } return true; } else { m_out << "tools::rroot::branch_element::read_leaves :" << " name " << m_name << " ref_cls " << fClassName << " :" << " type 0 with ID " << fID << " not treated." << std::endl; return false; } } m_out << "tools::rroot::branch_element::read_leaves :" << " name " << m_name << " ref_cls " << fClassName << " : type " << fType << " not treated, stream_type is " << fStreamerType << "." << std::endl; return false; /* /////////////////////////////////////////////////////// /// STL container ///////////////////////////////////// /////////////////////////////////////////////////////// if(fType==4) { // STL container master branch (has only the number of elements). //from v4-00-01 int n; if(!a_buffer.read(n)) return false; //fNdata = n; m_out << "tools::rroot::branch_element::read_leaves :" << " name " << m_name << " ref_cls " << fClassName << " : type " << fType << " not treated." << std::endl; return false; } else if(fType==41) { // STL container sub-branch (contains the elements). m_out << "tools::rroot::branch_element::read_leaves :" << " name " << m_name << " ref_cls " << fClassName << " : type " << fType << " not treated." << std::endl; return false; /////////////////////////////////////////////////////// /// TClonesArray container //////////////////////////// /////////////////////////////////////////////////////// } else if(fType==3) { // TClonesArray master branch (has only the number of elements). //from v4-00-01 int n; if(!a_buffer.read(n)) return false; //fNdata = n; //TClonesArray *clones = (TClonesArray*)fObject; //if (!clones) return; //if (clones->IsZombie()) return; //clones->Clear(); //clones->ExpandCreateFast(fNdata); m_out << "tools::rroot::branch_element::read_leaves :" << " name " << m_name << " ref_cls " << fClassName << " : type " << fType << " not treated." << std::endl; return false; } else if(fType==31) { // TClonesArray sub-branch (contains the elements). m_out << "tools::rroot::branch_element::read_leaves :" << " name " << m_name << " ref_cls " << fClassName << " : type " << fType << " not treated." << std::endl; return false; /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// } else if(fType<=2) { // branch in split mode //from v4-00-01 //if (fBranchCount) fNdata = (Int_t)fBranchCount->GetValue(0,0); //else fNdata = 1; //if (!fInfo) return; //fInfo->ReadBuffer(b,fObject,fID); //if (fStreamerType == 6) fNdata = (Int_t)GetValue(0,0); //from 3.0.06 //if (fID >= 0) { // fInfo->ReadBuffer(b,fAddress,fID); //} else if (fID == -1) { // top level branch in non split mode // char **ppointer = (char**)fAddress; // fInfo->ReadBuffer(b,*ppointer,fID); //} //m_out << "tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName << " :" // << " type " << fType << " with ID " << fID << "." // << " and then ?" // << std::endl; // read object ? bool created = false; if(!m_obj) { ifac::args args; m_obj = m_fac.create(fClassName,args); if(!m_obj) return false; created = true; } if(!m_obj->stream(a_buffer)){ m_out << "tools::rroot::branch_element::read_leaves :" << " name " << m_name << " ref_cls " << fClassName << " :" << " obj stream failed." << std::endl; if(created) {delete m_obj;m_obj = 0;} return false; } //m_out << "tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName << " :" // << " obj streamed." // << std::endl; return true; // } else if(fType==0) { // if(fID>=0) { // // branch in split mode // m_out << "tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName << " :" // << " type 0 with ID " << fID << "." // << std::endl; // return true; // // } else if(fID==-1) { // // top level branch in non split mode // m_out << "tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName << " :" // << " type 0 with ID " << fID // << " : fill object." // << std::endl; // if(!m_obj) { // m_out << "tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName << " :" // << " m_obj is null." // << std::endl; // return false; // } // if(!m_obj->stream(a_buffer)){ // m_out << "tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName << " :" // << " obj stream failed." // << std::endl; // return false; // } // return true; // } else { // m_out << "tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName << " :" // << " type 0 with ID " << fID << " not treated." // << std::endl; // return false; // } // //LHCb files : // } else if(fType==1) { // // parent branch is a base class branch. // // Ok, and then ? // m_out << "tools::rroot::branch_element::read_leaves :" // << " name " << m_name << " ref_cls " << fClassName << " :" // << " type " << fType << " with ID " << fID << "." // << std::endl; // return true; } else { m_out << "tools::rroot::branch_element::read_leaves :" << " name " << m_name << " ref_cls " << fClassName << " :" << " type " << fType << " with ID " << fID << "." << " unknown case." << std::endl; return false; } */ } virtual bool find_entry(ifile& a_file,uint64 a_entry,uint32& a_nbytes){ //The below line will call the upper read_leaves. if(!parent::find_entry(a_file,a_entry,a_nbytes)) return false; if(m_branches.size()) { //if(!m_obj) { // m_obj = m_fac.create(fClassName); // if(!m_obj) return false; //} tools_vforcit(branch*,m_branches,it) { uint32 n; if(!(*it)->find_entry(a_file,a_entry,n)) return false; a_nbytes += n; } } return true; } virtual bool show(std::ostream& a_out,ifile& a_file,uint64 a_entry){ uint32 n; if(!find_entry(a_file,a_entry,n)) return false; {std::string s; uint32 len = uint32(name().size())+128; sprintf(s,len," %-15s = ",name().c_str()); a_out << s;} a_out << m_obj << std::endl; return true; //return parent::show(a_out,a_file,a_entry); } public: branch_element(std::ostream& a_out,ifac& a_fac) :parent(a_out,a_fac) ,m_obj(0) ,fClassVersion(0) ,fID(0) ,fType(0) ,fStreamerType(-1) ,fBranchCount(0) //not owner ,fBranchCount_created(false) ,fBranchCount2(0) //not owner ,fBranchCount2_created(false) ,fNdata(1) {} virtual ~branch_element() { _clear(); if(m_obj) delete m_obj; } protected: branch_element(const branch_element& a_from):iro(a_from),parent(a_from){} branch_element& operator=(const branch_element&){return *this;} public: const std::string& class_name() const {return fClassName;} int type() const {return fType;} int streamer_type() const {return fStreamerType;} int id() const {return fID;} iro* object() {return m_obj;} int get_ndata() const {return fNdata;} template stl_vector* object_to_stl_vector() const { if(!m_obj) { m_out << "tools::rroot::branch_element::object_to_stl_vector : there is no object." << std::endl; return 0; } stl_vector* od = id_cast >(*m_obj); if(!od) { m_out << "tools::rroot::branch_element::object_to_stl_vector :" << " object of class " << sout(m_obj->s_cls()) << " not a tools::rroot::stl_vector." << std::endl; return 0; } return od; //WARNING : we are not owner. } obj_list* object_to_obj_list() const { if(!m_obj) { m_out << "tools::rroot::branch_element::object_to_obj_list : there is no object." << std::endl; return 0; } obj_list* od = id_cast(*m_obj); if(!od) { m_out << "tools::rroot::branch_element::object_to_obj_list :" << " object of class " << sout(m_obj->s_cls()) << " not a tools::rroot::obj_list." << std::endl; return 0; } return od; //WARNING : we are not owner. } template stl_vector* find_entry_vec(ifile& a_file,uint64 a_event) { unsigned int n; if(!find_entry(a_file,a_event,n)) { m_out << "tools::rroot::branch_element::find_entry_vec : find_entry() failed." << std::endl; return 0; } if(!m_obj) { m_out << "tools::rroot::branch_element::find_entry_vec : no object found." << std::endl; return 0; } stl_vector* od = id_cast >(*m_obj); if(!od) { m_out << "tools::rroot::branch_element::find_entry_vec :" << " object not a tools::rroot::stl_vector." << std::endl; return 0; } return od; //WARNING : we are not owner. } protected: void _clear() { if(fBranchCount_created) {delete fBranchCount;fBranchCount = 0;fBranchCount_created = false;} if(fBranchCount2_created) {delete fBranchCount2;fBranchCount2 = 0;fBranchCount2_created = false;} } protected: iro* m_obj; protected: std::string fClassName; //Class name of referenced object int fClassVersion; //Version number of class int fID; //element serial number in fInfo int fType; //branch type int fStreamerType; //branch streamer type branch_element* fBranchCount; // pointer to primary branchcount branch bool fBranchCount_created; branch_element* fBranchCount2; // pointer to secondary branchcount branch bool fBranchCount2_created; int fNdata; // Number of data in this branch }; }} #ifdef TOOLS_RROOT_BRANCH_ELEMENT_DUMP #undef TOOLS_RROOT_BRANCH_ELEMENT_DUMP #endif #endif //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// /* In v4-00-01 version 8 : case 1: {b.ReadFastArray((Char_t*) fAddress, n); break;} case 2: {b.ReadFastArray((Short_t*) fAddress, n); break;} case 3: {b.ReadFastArray((Int_t*) fAddress, n); break;} case 4: {b.ReadFastArray((Long_t*) fAddress, n); break;} case 5: {b.ReadFastArray((Float_t*) fAddress, n); break;} case 6: {b.ReadFastArray((Int_t*) fAddress, n); break;} case 8: {b.ReadFastArray((Double_t*)fAddress, n); break;} case 11: {b.ReadFastArray((UChar_t*) fAddress, n); break;} case 12: {b.ReadFastArray((UShort_t*)fAddress, n); break;} case 13: {b.ReadFastArray((UInt_t*) fAddress, n); break;} case 14: {b.ReadFastArray((ULong_t*) fAddress, n); break;} case 15: {b.ReadFastArray((Long64_t*)fAddress, n); break;} case 16: {b.ReadFastArray((ULong64_t*)fAddress, n); break;} case 9: {Double_t *xx = (Double_t*)fAddress; Float_t afloat; for (Int_t ii=0;ii> afloat; xx[ii] = Double_t(afloat); } break;} */ /* 6.12.06 version 10 : fStreamerType : from meta/inc/TVirtualStreamerInfo.h : enum EReadWrite { kBase = 0, kOffsetL = 20, kOffsetP = 40, kCounter = 6, kCharStar = 7, kChar = 1, kShort = 2, kInt = 3, kLong = 4, kFloat = 5, kDouble = 8, kDouble32= 9, kUChar = 11, kUShort = 12, kUInt = 13, kULong = 14, kBits = 15, kLong64 = 16, kULong64 = 17, kBool = 18, kFloat16 = 19, kObject = 61, kAny = 62, kObjectp = 63, kObjectP = 64, kTString = 65, kTObject = 66, kTNamed = 67, kAnyp = 68, kAnyP = 69, kAnyPnoVT = 70, kSTLp = 71, kSkip = 100, kSkipL = 120, kSkipP = 140, kConv = 200, kConvL = 220, kConvP = 240, kSTL = ROOT::kSTLany, // 300 kSTLstring = ROOT::kSTLstring, // 365 kStreamer = 500, kStreamLoop = 501, kCache = 600, // Cache the value in memory than is not part of the object but is accessible via a SchemaRule kArtificial = 1000, kCacheNew = 1001, kCacheDelete = 1002, kNeedObjectForVirtualBaseClass = 99997, kMissing = 99999 }; // Some comments about EReadWrite // kBase : base class element // kOffsetL : fixed size array // kOffsetP : pointer to object // kCounter : counter for array size // kCharStar: pointer to array of char // kBits : TObject::fBits in case of a referenced object // kObject : Class derived from TObject // kObjectp : Class* derived from TObject and with comment field //->Class // kObjectP : Class* derived from TObject and with NO comment field //->Class // kAny : Class not derived from TObject // kAnyp : Class* not derived from TObject with comment field //->Class // kAnyP : Class* not derived from TObject with NO comment field //->Class // kAnyPnoVT: Class* not derived from TObject with NO comment field //->Class and Class has NO virtual table // kSTLp : Pointer to STL container. // kTString : TString, special case // kTObject : TObject, special case // kTNamed : TNamed , special case */