// 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" 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; 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; std::string fParentName; if(!a_buffer.read(fParentName)) return false; std::string fCloneName; if(!a_buffer.read(fCloneName)) return false; int dummy_int; if(!a_buffer.read(dummy_int)) return false; //fCheckSum if(v>=10) { short dummy_short; if(!a_buffer.read(dummy_short)) return false; //fClassVersion } else { if(!a_buffer.read(dummy_int)) return false; //fClassVersion } if(!a_buffer.read(fID)) return false; if(!a_buffer.read(fType)) return false; if(!a_buffer.read(fStreamerType)) return false; if(!a_buffer.read(dummy_int)) return false; //fMaximum 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; } 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; fNdata = n; 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(); 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; } 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(); 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; } (*vec)[ii] = afloat; } return true; } else if(fStreamerType==kDouble) { int ndata = fBranchCount->get_ndata(); 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(); 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(); 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(); 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(); 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(); 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; } } else if(fType==0) { // to read wroot.root of examples/cpp/wroot.cpp. if((fID==-1)|| (fID==1) // for pmx to read LHCb files : ){ if(fBranchCount) { fNdata = fBranchCount->get_ndata(); } 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; } 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()) { 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; } 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 }; }} #endif