495 lines
15 KiB
Plaintext
495 lines
15 KiB
Plaintext
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
|
// See the file tools.license for terms.
|
|
|
|
#ifndef tools_rroot_tree
|
|
#define tools_rroot_tree
|
|
|
|
#include "ifac"
|
|
#include "branch_element"
|
|
#include "../sout"
|
|
#include "iobject"
|
|
|
|
namespace tools {
|
|
namespace rroot {
|
|
|
|
inline const std::string& TTree_cls(){
|
|
static const std::string s_v("TTree");
|
|
return s_v;
|
|
}
|
|
|
|
class tree : public virtual iobject {
|
|
public:
|
|
static const std::string& s_class() {
|
|
static const std::string s_v("tools::rroot::tree");
|
|
return s_v;
|
|
}
|
|
virtual const std::string& s_cls() const {return s_class();}
|
|
public: //iobject
|
|
virtual const std::string& name() const {return m_name;}
|
|
virtual const std::string& title() const {return m_title;}
|
|
virtual const std::string& store_class_name() const {
|
|
static const std::string s_v("TTree");
|
|
return s_v;
|
|
}
|
|
public:
|
|
tree(ifile& a_file,ifac& a_fac)
|
|
:m_file(a_file)
|
|
,m_fac(a_fac)
|
|
,m_out(a_file.out())
|
|
,m_name("")
|
|
,m_title("")
|
|
,m_branches(a_fac)
|
|
,m_entries(0)
|
|
{
|
|
#ifdef TOOLS_MEM
|
|
mem::increment(s_class().c_str());
|
|
#endif
|
|
}
|
|
virtual ~tree(){
|
|
#ifdef TOOLS_MEM
|
|
mem::decrement(s_class().c_str());
|
|
#endif
|
|
}
|
|
protected:
|
|
tree(const tree& a_from)
|
|
:iobject(a_from)
|
|
,m_file(a_from.m_file)
|
|
,m_fac(a_from.m_fac)
|
|
,m_out(a_from.m_out)
|
|
,m_branches(m_fac)
|
|
{}
|
|
tree& operator=(const tree&){return *this;}
|
|
public:
|
|
std::ostream& out() const {return m_out;}
|
|
|
|
ifile& file() {return m_file;}
|
|
ifac& fac() {return m_fac;}
|
|
|
|
const std::vector<branch*>& branches() const {return m_branches;}
|
|
|
|
bool find_entry(uint64 a_entry,uint32& a_nbytes) {
|
|
a_nbytes = 0;
|
|
if(a_entry>=m_entries) return false;
|
|
int nbytes = 0;
|
|
//fReadEntry = a_entry;
|
|
tools_vforit(branch*,m_branches,it) {
|
|
uint32 n;
|
|
if(!(*it)->find_entry(m_file,a_entry,n)) return false;
|
|
nbytes += n;
|
|
}
|
|
a_nbytes = nbytes;
|
|
return true;
|
|
}
|
|
|
|
void dump(std::ostream& a_out,const std::string& a_spaces = "",const std::string& a_indent = " "){
|
|
a_out << a_spaces
|
|
<< "tree :"
|
|
<< " name=" << sout(m_name)
|
|
<< " title=" << sout(m_title)
|
|
<< " entries=" << m_entries
|
|
<< std::endl;
|
|
_dump_branches(a_out,m_branches,a_spaces+a_indent,a_indent);
|
|
}
|
|
|
|
branch* find_branch(const std::string& a_name,bool a_recursive = false) const {
|
|
return _find_branch(m_branches,a_name,a_recursive);
|
|
}
|
|
|
|
branch_element* find_branch_element(const std::string& a_name,bool a_recursive = false) const {
|
|
branch* b = _find_branch(m_branches,a_name,a_recursive);
|
|
if(!b) return 0;
|
|
return id_cast<branch,branch_element>(*b);
|
|
}
|
|
|
|
base_leaf* find_leaf(const std::string& a_name,bool a_recursive = false) const {
|
|
return _find_leaf(m_branches,a_name,a_recursive);
|
|
}
|
|
|
|
void find_leaves(std::vector<base_leaf*>& a_leaves) const {
|
|
a_leaves.clear();
|
|
_find_leaves(m_branches,a_leaves);
|
|
}
|
|
|
|
void find_branches(std::vector<branch*>& a_branches) const {
|
|
a_branches.clear();
|
|
_find_branches(m_branches,a_branches);
|
|
}
|
|
|
|
branch* find_leaf_branch(const base_leaf& a_leaf) const {return _find_leaf_branch(m_branches,a_leaf);}
|
|
|
|
bool show(std::ostream& a_out,uint64 a_entry){
|
|
a_out << "======> EVENT:" << a_entry << std::endl;
|
|
tools_vforit(branch*,m_branches,it) {
|
|
if(!(*it)->show(a_out,m_file,a_entry)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
uint64 entries() const {return m_entries;}
|
|
|
|
virtual bool stream(buffer& a_buffer) { //virtual for iobject.
|
|
//uint64 m_tot_bytes;
|
|
//uint64 m_zip_bytes;
|
|
//uint64 m_saved_bytes;
|
|
|
|
short vers;
|
|
unsigned int s, c;
|
|
if(!a_buffer.read_version(vers,s,c)) return false;
|
|
|
|
//::printf("debug : tree::stream : version %d count %d\n",vers,c);
|
|
|
|
//if (vers > 4) {
|
|
//TTree::Class()->ReadBuffer(b, this, vers, s, c);
|
|
//if (fEstimate <= 10000) fEstimate = 1000000;
|
|
//m_saved_bytes = m_tot_bytes;
|
|
//fDirectory = gDirectory;
|
|
//gDirectory->Append(this);
|
|
//return;
|
|
//}
|
|
|
|
if(!Named_stream(a_buffer,m_name,m_title)) return false;
|
|
|
|
{short color,style,width;
|
|
if(!AttLine_stream(a_buffer,color,style,width)) return false;}
|
|
{short color,style;
|
|
if(!AttFill_stream(a_buffer,color,style)) return false;}
|
|
if(!AttMarker_stream(a_buffer)) return false;
|
|
|
|
if(vers<=4) {
|
|
int dummy_int;
|
|
|
|
if(!a_buffer.read(dummy_int)) return false; //fScanField
|
|
if(!a_buffer.read(dummy_int)) return false; //fMaxEntryLoop
|
|
{int fMaxVirtualSize;
|
|
if(!a_buffer.read(fMaxVirtualSize)) return false;}
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
m_entries = uint64(v);}
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_tot_bytes = uint64(v);
|
|
}
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_zip_bytes = uint64(v);
|
|
}
|
|
{int fAutoSave;
|
|
if(!a_buffer.read(fAutoSave)) return false;}
|
|
if(!a_buffer.read(dummy_int)) return false; //fEstimate
|
|
|
|
} else if(vers<=9) {
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
m_entries = uint64(v);}
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_tot_bytes = uint64(v);
|
|
}
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_zip_bytes = uint64(v);
|
|
}
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_saved_bytes = uint64(v);
|
|
}
|
|
|
|
int dummy_int;
|
|
if(!a_buffer.read(dummy_int)) return false; //fTimerInterval
|
|
if(!a_buffer.read(dummy_int)) return false; //fScanField
|
|
if(!a_buffer.read(dummy_int)) return false; //fUpdate
|
|
if(!a_buffer.read(dummy_int)) return false; //fMaxEntryLoop
|
|
|
|
{int fMaxVirtualSize;
|
|
if(!a_buffer.read(fMaxVirtualSize)) return false;}
|
|
{int fAutoSave;
|
|
if(!a_buffer.read(fAutoSave)) return false;}
|
|
if(!a_buffer.read(dummy_int)) return false; //fEstimate
|
|
|
|
} else if(vers<16) { //FIXME : what is the exact version ?
|
|
double dummy_double;
|
|
int dummy_int;
|
|
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
m_entries = uint64(v);}
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_tot_bytes = uint64(v);
|
|
}
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_zip_bytes = uint64(v);
|
|
}
|
|
{double v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_saved_bytes = uint64(v);
|
|
}
|
|
if(!a_buffer.read(dummy_double)) return false; //fWeight
|
|
if(!a_buffer.read(dummy_int)) return false; //fTimerInterval
|
|
if(!a_buffer.read(dummy_int)) return false; //fScanField
|
|
if(!a_buffer.read(dummy_int)) return false; //fUpdate
|
|
if(!a_buffer.read(dummy_int)) return false; //fMaxEntryLoop
|
|
|
|
{int fMaxVirtualSize;
|
|
if(!a_buffer.read(fMaxVirtualSize)) return false;}
|
|
{int fAutoSave;
|
|
if(!a_buffer.read(fAutoSave)) return false;}
|
|
if(!a_buffer.read(dummy_int)) return false; //fEstimate
|
|
|
|
} else { //vers>=16
|
|
double dummy_double;
|
|
int dummy_int;
|
|
int64 dummy_int64;
|
|
|
|
{uint64 v;
|
|
if(!a_buffer.read(v)) return false;
|
|
m_entries = v;}
|
|
{uint64 v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_tot_bytes = v;
|
|
}
|
|
{uint64 v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_zip_bytes = v;
|
|
}
|
|
{uint64 v;
|
|
if(!a_buffer.read(v)) return false;
|
|
//m_saved_bytes = v;
|
|
}
|
|
if(vers>=18) {
|
|
if(!a_buffer.read(dummy_int64)) return false; //fFlushedBytes
|
|
}
|
|
|
|
if(!a_buffer.read(dummy_double)) return false; //fWeight
|
|
|
|
if(!a_buffer.read(dummy_int)) return false; //fTimerInterval
|
|
if(!a_buffer.read(dummy_int)) return false; //fScanField
|
|
if(!a_buffer.read(dummy_int)) return false; //fUpdate
|
|
|
|
if(vers>=18) {
|
|
if(!a_buffer.read(dummy_int)) return false; //fDefaultEntryOffsetLen
|
|
}
|
|
int fNClusterRange;
|
|
if(vers>=20) {
|
|
if(!a_buffer.read(fNClusterRange)) return false; //fNClusterRange
|
|
}
|
|
|
|
if(!a_buffer.read(dummy_int64)) return false; //fMaxEntries
|
|
if(!a_buffer.read(dummy_int64)) return false; //fMaxEntryLoop
|
|
{uint64 fMaxVirtualSize;
|
|
if(!a_buffer.read(fMaxVirtualSize)) return false;}
|
|
{uint64 fAutoSave;
|
|
if(!a_buffer.read(fAutoSave)) return false;}
|
|
if(vers>=18) {
|
|
if(!a_buffer.read(dummy_int64)) return false; //fAutoFlush
|
|
}
|
|
if(!a_buffer.read(dummy_int64)) return false; //fEstimate
|
|
if(vers>=20) {
|
|
int64* fClusterRangeEnd = 0; ///<[fNClusterRange] Last entry of a cluster range.
|
|
if(!fixed_array_stream<int64>(a_buffer,fNClusterRange,fClusterRangeEnd)) return false;
|
|
delete [] fClusterRangeEnd;
|
|
int64* fClusterSize = 0; ///<[fNClusterRange] Number of entries in each cluster for a given range.
|
|
if(!fixed_array_stream<int64>(a_buffer,fNClusterRange,fClusterSize)) return false;
|
|
delete [] fClusterSize;
|
|
dummy _dummy;
|
|
if(!_dummy.stream(a_buffer)) { //TIOFeatures fIOFeatures
|
|
m_out << "tools::rroot::tree::stream : can't read (dummy) TIOFeatures." << std::endl;
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
//FIXME if (fEstimate <= 10000) fEstimate = 1000000;
|
|
|
|
//TObjArray
|
|
//The below m_branches.read will create leaves.
|
|
//::printf("debug : tree : read branches : begin\n");
|
|
{ifac::args args;
|
|
if(!m_branches.stream(a_buffer,args)) {
|
|
m_out << "tools::rroot::tree::stream : "
|
|
<< "can't read branches."
|
|
<< std::endl;
|
|
return false;
|
|
}}
|
|
//::printf("debug : tree : read branches : end\n");
|
|
|
|
//TObjArray
|
|
// We read leaves in order to keep streaming synchronisation.
|
|
// In fact m_leaves are references to existing leaves read by
|
|
// the branches in the upper line of code.
|
|
//::printf("debug : tree : read leaves : begin\n");
|
|
{obj_array<base_leaf> m_leaves(m_fac);
|
|
//branch b(m_out,m_fac);
|
|
ifac::args args;
|
|
//args[ifac::arg_branch()] = &b;
|
|
if(!m_leaves.stream(a_buffer,args)) {
|
|
m_out << "tools::rroot::tree::stream : "
|
|
<< "can't read leaves."
|
|
<< std::endl;
|
|
return false;
|
|
}}
|
|
//::printf("debug : tree : read leaves : end\n");
|
|
|
|
if(vers>=10) {
|
|
//TList* fAliases
|
|
if(!dummy_TXxx_pointer_stream(a_buffer,m_fac)) {
|
|
m_out << "tools::rroot::tree::stream : "
|
|
<< "can't read fAliases."
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//m_saved_bytes = m_tot_bytes;
|
|
{std::vector<double> v;
|
|
if(!Array_stream<double>(a_buffer,v)) return false;} //fIndexValues TArrayD
|
|
|
|
{std::vector<int> v;
|
|
if(!Array_stream<int>(a_buffer,v)) return false;} // fIndex (TArrayI).
|
|
|
|
if(vers>=16) {
|
|
//TVirtualIndex* fTreeIndex //FIXME ???
|
|
if(!dummy_TXxx_pointer_stream(a_buffer,m_fac)) {
|
|
m_out << "tools::rroot::tree::stream : "
|
|
<< "can't read fTreeIndex."
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if(vers>=6) {
|
|
//TList* fFriends
|
|
if(!dummy_TXxx_pointer_stream(a_buffer,m_fac)) {
|
|
m_out << "tools::rroot::tree::stream : "
|
|
<< "can't read fFriends."
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if(vers>=16) {
|
|
//TList* fUserInfo
|
|
if(!dummy_TXxx_pointer_stream(a_buffer,m_fac)) {
|
|
m_out << "tools::rroot::tree::stream : "
|
|
<< "can't read fUserInfo."
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
//TBranchRef* fBranchRef
|
|
if(!dummy_TXxx_pointer_stream(a_buffer,m_fac)) {
|
|
m_out << "tools::rroot::tree::stream : "
|
|
<< "can't read fBranchRef."
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if(!a_buffer.check_byte_count(s,c,TTree_cls())) return false;
|
|
|
|
return true;
|
|
}
|
|
protected:
|
|
void _dump_branches(std::ostream& a_out,
|
|
const std::vector<branch*>& a_bs,
|
|
const std::string& a_spaces = "",
|
|
const std::string& a_indent = " "){
|
|
tools_vforcit(branch*,a_bs,it) {
|
|
if(branch_element* be = safe_cast<branch,branch_element>(*(*it))) {
|
|
a_out << a_spaces
|
|
<< "branch_element :"
|
|
<< " name=" << sout((*it)->name())
|
|
<< " title=" << sout((*it)->title())
|
|
<< " entry_number=" << be->entry_number()
|
|
<< " ref_cls=" << sout(be->class_name())
|
|
<< " (type=" << be->type()
|
|
<< ",id=" << be->id()
|
|
<< ",stype=" << be->streamer_type()
|
|
<< ")."
|
|
<< std::endl;
|
|
} else {
|
|
a_out << a_spaces
|
|
<< "branch :"
|
|
<< " name=" << sout((*it)->name())
|
|
<< " title=" << sout((*it)->title())
|
|
<< " entry_number=" << (*it)->entry_number()
|
|
<< std::endl;
|
|
}
|
|
|
|
|
|
{const std::vector<base_leaf*>& lvs = (*it)->leaves();
|
|
tools_vforcit(base_leaf*,lvs,itl) {
|
|
a_out << a_spaces << a_indent
|
|
<< "leave :"
|
|
<< " name=" << sout((*itl)->name())
|
|
<< " title=" << sout((*itl)->title())
|
|
<< " cls=" << sout((*itl)->s_cls())
|
|
<< std::endl;
|
|
}}
|
|
|
|
_dump_branches(a_out,(*it)->branches(),a_spaces+a_indent,a_indent);
|
|
}
|
|
}
|
|
|
|
static branch* _find_branch(const std::vector<branch*>& a_bs,const std::string& a_name,bool a_recursive) {
|
|
tools_vforcit(branch*,a_bs,it) {
|
|
if(rcmp((*it)->name(),a_name)) return *it;
|
|
if(a_recursive) {
|
|
branch* br = _find_branch((*it)->branches(),a_name,a_recursive);
|
|
if(br) return br;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static base_leaf* _find_leaf(const std::vector<branch*>& a_bs,const std::string& a_name,bool a_recursive) {
|
|
tools_vforcit(branch*,a_bs,it) {
|
|
tools_vforcit(base_leaf*,(*it)->leaves(),itl) {
|
|
if(rcmp((*itl)->name(),a_name)) return *itl;
|
|
}
|
|
if(a_recursive) {
|
|
base_leaf* lf = _find_leaf((*it)->branches(),a_name,a_recursive);
|
|
if(lf) return lf;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void _find_leaves(const std::vector<branch*>& a_bs,std::vector<base_leaf*>& a_leaves) {
|
|
tools_vforcit(branch*,a_bs,it) {
|
|
tools_vforcit(base_leaf*,(*it)->leaves(),itl) a_leaves.push_back(*itl);
|
|
_find_leaves((*it)->branches(),a_leaves);
|
|
}
|
|
}
|
|
|
|
static void _find_branches(const std::vector<branch*>& a_bs,std::vector<branch*>& a_branches){
|
|
tools_vforcit(branch*,a_bs,it) {
|
|
a_branches.push_back(*it);
|
|
_find_branches((*it)->branches(),a_branches);
|
|
}
|
|
}
|
|
|
|
static branch* _find_leaf_branch(const std::vector<branch*>& a_bs,const base_leaf& a_leaf) {
|
|
tools_vforcit(branch*,a_bs,itb) {
|
|
tools_vforcit(base_leaf*,(*itb)->leaves(),itl) {if(*itl==&a_leaf) return *itb;}
|
|
{branch* br = _find_leaf_branch((*itb)->branches(),a_leaf);
|
|
if(br) return br;}
|
|
}
|
|
return 0;
|
|
}
|
|
protected:
|
|
ifile& m_file;
|
|
ifac& m_fac;
|
|
std::ostream& m_out;
|
|
//Named
|
|
std::string m_name;
|
|
std::string m_title;
|
|
|
|
obj_array<branch> m_branches;
|
|
uint64 m_entries; // Number of entries
|
|
};
|
|
|
|
}}
|
|
|
|
#endif
|