// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_rroot_ntuple #define tools_rroot_ntuple // to have same API than rcsv::ntuple. #include "../rntuple" #include "tree" #include "leaf" #include "stl_vector" #include "../cids" #include "../vfind" #include "../vmanip" #include "../ntuple_binding" #ifdef TOOLS_MEM #include "../mem" #endif namespace tools { namespace rroot { class ntuple : public virtual read::intuple { public: static const std::string& s_class() { static const std::string s_v("tools::rroot::ntuple"); return s_v; } public: //intuple virtual void start() {m_index = -1;} virtual bool next() { m_index++; if((uint64)m_index>=m_tree.entries()) return false; return true; } virtual read::icol* find_icol(const std::string& a_name){ return find_named(m_cols,a_name); } virtual const std::vector& columns() const {return m_cols;} public: template class column : public virtual read::icolumn { typedef read::icolumn parent; public: static cid id_class() {return 200+_cid(T());} public: //icol virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) {return p;} return parent::cast(a_class); } virtual cid id_cls() const {return id_class();} public: //icol virtual const std::string& name() const {return m_leaf.name();} public: //icolumn virtual bool get_entry(T& a_v) const { unsigned int n; if(!m_leaf.branch().find_entry(uint32(m_index),n)) { a_v = T(); return false; } a_v = m_leaf.value(); return true; } virtual bool fetch_entry() const { //NOTE : it is ok to have a NULL m_user_var. unsigned int n; if(!m_leaf.branch().find_entry(uint32(m_index),n)) { if(m_user_var) *m_user_var = T(); return false; } if(m_user_var) *m_user_var = m_leaf.value(); return true; } public: column(leaf& a_leaf,int64& a_index,T* a_user_var = 0) :m_leaf(a_leaf) ,m_index(a_index) //WARNING : we keep the ref ! ,m_user_var(a_user_var) //not owner {} virtual ~column(){} protected: column(const column& a_from) :read::intuple(a_from) ,parent(a_from) ,m_leaf(a_from.m_leaf) ,m_index(a_from.m_index) ,m_user_var(a_from.m_user_var) {} column& operator=(const column& a_from){ if(&a_from==this) return *this; m_user_var = a_from.m_user_var; return *this; } protected: leaf& m_leaf; int64& m_index; //WARNING : a ref. T* m_user_var; }; class column_string : public virtual read::icol { public: static cid id_class() { static const std::string s_v; return _cid(s_v); } public: //icol virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) return p; return 0; } virtual cid id_cls() const {return id_class();} virtual const std::string& name() const {return m_leaf.name();} public: virtual bool fetch_entry() const { //NOTE : it is ok to have a NULL m_user_var. unsigned int n; if(!m_leaf.branch().find_entry(uint32(m_index),n)) { if(m_user_var) *m_user_var = std::string(); return false; } if(m_user_var) *m_user_var = m_leaf.value(); return true; } public: column_string(leaf_string& a_leaf,int64& a_index,std::string* a_user_var = 0) :m_leaf(a_leaf) ,m_index(a_index) //WARNING : we keep the ref ! ,m_user_var(a_user_var) //not owner {} virtual ~column_string(){} protected: column_string(const column_string& a_from) :read::icol(a_from) ,m_leaf(a_from.m_leaf) ,m_index(a_from.m_index) ,m_user_var(a_from.m_user_var) {} column_string& operator=(const column_string& a_from){ if(&a_from==this) return *this; m_user_var = a_from.m_user_var; return *this; } protected: leaf_string& m_leaf; int64& m_index; //WARNING : a ref. std::string* m_user_var; }; template class column_element : public virtual read::icolumn { typedef read::icolumn parent; public: static cid id_class() {return 300+_cid(T());} public: //icol virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) {return p;} return parent::cast(a_class); } virtual cid id_cls() const {return id_class();} public: //icol virtual const std::string& name() const {return m_leaf.name();} public: //icolumn virtual bool get_entry(T& a_v) const { unsigned int n; if(!m_leaf.branch().find_entry(uint32(m_index),n)) {a_v = T();return false;} if(!m_be) {a_v = T();return false;} iro* obj = m_be->object(); //Not owner. if(!obj) {a_v = T();return false;} RT* v = id_cast(*obj); if(!v) {a_v = T();return false;} a_v = *v; //it assumes a T::operator=(RT) return true; } virtual bool fetch_entry() const { unsigned int n; if(!m_leaf.branch().find_entry(uint32(m_index),n)) { if(m_user_var) *m_user_var = T(); return false; } if(!m_be) { if(m_user_var) *m_user_var = T(); return false; } iro* obj = m_be->object(); //Not owner. if(!obj) { if(m_user_var) *m_user_var = T(); return false; } RT* v = id_cast(*obj); if(!v) { if(m_user_var) *m_user_var = T(); return false; } if(m_user_var) *m_user_var = *v; //it assumes a T::operator=(RT) return true; } public: column_element(leaf_element& a_leaf,int64& a_index,T* a_user_var = 0) :m_leaf(a_leaf) ,m_index(a_index) //WARNING : we keep the ref ! ,m_be(0) ,m_user_var(a_user_var) //not owner { m_be = safe_cast(m_leaf.branch()); } virtual ~column_element(){} protected: column_element(const column_element& a_from) :read::intuple(a_from),parent(a_from) ,m_leaf(a_from.m_leaf) ,m_index(a_from.m_index) ,m_be(a_from.m_be) ,m_user_var(a_from.m_user_var) {} column_element& operator=(const column_element& a_from){ if(&a_from==this) return *this; m_be = a_from.m_be; m_user_var = a_from.m_user_var; return *this; } protected: leaf_element& m_leaf; int64& m_index; //WARNING : a ref. branch_element* m_be; T* m_user_var; }; public: ntuple(tree& a_tree):m_tree(a_tree),m_index(-1){ #ifdef TOOLS_MEM mem::increment(s_class().c_str()); #endif } virtual ~ntuple() { tools::clear(m_cols); #ifdef TOOLS_MEM mem::decrement(s_class().c_str()); #endif } protected: ntuple(const ntuple& a_from) :read::intuple(a_from),m_tree(a_from.m_tree){ #ifdef TOOLS_MEM mem::increment(s_class().c_str()); #endif } ntuple& operator=(const ntuple&){return *this;} public: bool initialize(std::ostream& a_out,const ntuple_binding& a_bd = ntuple_binding()) { tools::clear(m_cols); std::vector leaves = m_tree.find_leaves(); tools_vforcit(base_leaf*,leaves,it) { base_leaf* bl = (*it); if(find_named(m_cols,bl->name())) { a_out << "tools::rroot::ntuple::initialize :" << " column with name " << sout(bl->name()) << " already exists." << std::endl; tools::clear(m_cols); return false; } //a_out << "tools::rroot::ntuple::initialize :" // << " entries " << bl->branch().entry_number() << "." // << std::endl; if(leaf* lf = safe_cast >(*bl) ){ column* col = new column(*lf,m_index,a_bd.find_variable(bl->name())); m_cols.push_back(col); } else if(leaf* ld = safe_cast >(*bl) ){ column* col = new column(*ld,m_index,a_bd.find_variable(bl->name())); m_cols.push_back(col); } else if(leaf* li = safe_cast >(*bl) ){ column* col = new column(*li,m_index,a_bd.find_variable(bl->name())); m_cols.push_back(col); } else if(leaf_string* ls = safe_cast(*bl) ){ column_string* col = new column_string(*ls,m_index,a_bd.find_variable(bl->name())); m_cols.push_back(col); } else if(leaf_element* le = safe_cast(*bl) ){ branch_element* be = safe_cast(le->branch()); if(be->class_name()=="vector") { typedef std::string el_t; typedef column_element< stl_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); //unsigned int n; //if(!be->find_entry(0,n)) {} } else if(be->class_name()=="vector") { typedef unsigned short el_t; typedef column_element< stl_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector") { typedef short el_t; typedef column_element< stl_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector") { typedef unsigned int el_t; typedef column_element< stl_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector") { //beurk! typedef uint64 el_t; //it is ok to map to an uint64 ? typedef column_element< stl_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); //unsigned int n; //if(!be->find_entry(0,n)) {} } else if(be->class_name()=="vector") { typedef int el_t; typedef column_element< stl_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector") { typedef float el_t; typedef column_element< stl_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector") { typedef double el_t; typedef column_element< stl_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector >") { typedef std::vector el_t; typedef column_element< stl_vector_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector >") { typedef std::vector el_t; typedef column_element< stl_vector_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector >") { typedef std::vector el_t; typedef column_element< stl_vector_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector >") { typedef std::vector el_t; typedef column_element< stl_vector_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else if(be->class_name()=="vector >") { typedef std::vector el_t; typedef column_element< stl_vector_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); //unsigned int n; //if(!be->find_entry(0,n)) {} } else if(be->class_name()=="vector >") { typedef std::vector el_t; typedef column_element< stl_vector_vector , std::vector > ce_t; ce_t* col = new ce_t(*le,m_index,a_bd.find_variable< std::vector >(bl->name())); m_cols.push_back(col); } else { a_out << "tools::rroot::ntuple::initialize :" << " WARNING : leaf element" << " with name " << tools::sout(bl->name()) << ",title " << tools::sout(bl->title()) << " br_elem class name " << be->class_name() << "." << " entries " << be->entry_number() << "." << std::endl; } } else { a_out << "tools::rroot::ntuple::initialize :" << " WARNING : column type not yet handled for leaf" << " with name " << tools::sout(bl->name()) << " and title " << tools::sout(bl->title()) << "." << " s_cls() is " << tools::sout(bl->s_cls()) << "." << " Not fatal." << std::endl; } } unsigned int num = m_cols.size(); if(!num) { a_out << "tools::rroot::ntuple::initialize :" << " zero columns." << std::endl; return false; } //a_out << "tools::rroot::ntuple::initialize :" // << " number of columns " << num << "." // << std::endl; return true; } bool get_row() const { bool status = true; tools_vforcit(read::icol*,m_cols,it) { if(!(*it)->fetch_entry()) status = false; } return status; } protected: tree& m_tree; std::vector m_cols; int64 m_index; }; }} #endif