// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_waxml_ntuple #define tools_waxml_ntuple // A ntuple class to write at the aida tuple format. // Each add_row() write a row at the aida tuple format. #include "../vfind" #include "../vmanip" #include "../sout" #include "../tos" #include // for sub_ntuple : #include "../scast" #include namespace tools { namespace waxml { class ntuple { protected: static cid _cid(int) {return 1;} static cid _cid(float) {return 2;} static cid _cid(double) {return 3;} class iobj { public: virtual ~iobj(){} public: virtual void* cast(cid) const = 0; virtual const std::string& name() const = 0; virtual std::string aida_type() const = 0; }; class leaf : public virtual iobj { public: static cid id_class() {return 100;} public: //iobj virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) {return p;} return 0; } public: virtual std::string s_def() const = 0; virtual std::string s_value() const = 0; public: leaf(){} virtual ~leaf(){} leaf(const leaf& a_from):iobj(a_from){} leaf& operator=(const leaf&){return *this;} }; static const std::string& s_aida_type(int) { static const std::string s_v("int"); return s_v; } static const std::string& s_aida_type(float) { static const std::string s_v("float"); return s_v; } static const std::string& s_aida_type(double) { static const std::string s_v("double"); return s_v; } public: template class column : public leaf { public: static cid id_class() {return 200+_cid(T());} public: //iobj virtual void* cast(cid a_class) const { if(void* p = cmp_cast< column >(this,a_class)) {return p;} return leaf::cast(a_class); } virtual const std::string& name() const {return m_name;} virtual std::string aida_type() const {return s_aida_type(T());} public: //leaf virtual std::string s_def() const {return tos(m_def);} virtual std::string s_value() const {return tos(m_tmp);} public: column(const std::string& a_name,const T& a_def) :m_name(a_name),m_def(a_def),m_tmp(a_def) {} virtual ~column(){} protected: column(const column& a_from) :leaf(a_from) ,m_name(a_from.m_name) ,m_def(a_from.m_def) ,m_tmp(a_from.m_tmp) {} column& operator=(const column& a_from){ m_name = a_from.m_name; m_def = a_from.m_def; m_tmp = a_from.m_tmp; return *this; } public: bool fill(const T& a_value) {m_tmp = a_value;return true;} protected: std::string m_name; T m_def; T m_tmp; }; class sub_ntuple : public virtual iobj { public: static cid id_class() {return 300;} public: //iobj virtual void* cast(cid a_class) const { if(void* p = cmp_cast(this,a_class)) {return p;} return 0; } virtual const std::string& name() const {return m_name;} virtual std::string aida_type() const {return "ITuple";} public: sub_ntuple(const std::string& a_name, const std::string& a_spaces) :m_name(a_name),m_spaces(a_spaces){} virtual ~sub_ntuple(){} protected: sub_ntuple(const sub_ntuple& a_from) :iobj(a_from),m_name(a_from.m_name){} sub_ntuple& operator=(const sub_ntuple&){return *this;} public: template column* create_column(const std::string& a_name, const T& a_def = T()) { if(find_named(m_cols,a_name)) return 0; column* col = new column(a_name,a_def); if(!col) return 0; m_cols.push_back(col); return col; } sub_ntuple* create_sub_ntuple(const std::string& a_name){ if(find_named(m_cols,a_name)) return 0; std::string spaces; for(unsigned int i=0;i<4;i++) spaces += " "; sub_ntuple* col = new sub_ntuple(a_name,m_spaces+spaces); if(!col) return 0; m_cols.push_back(col); return col; } const std::vector& columns() const {return m_cols;} std::string booking() const { std::string s; get_booking(m_cols,s); return s; } void reset() {m_tmp.clear();} const std::string& value() const {return m_tmp;} bool add_row() { if(m_cols.empty()) return false; std::ostringstream sout; sout << m_spaces << "" << std::endl; std::vector::const_iterator it; for(it=m_cols.begin();it!=m_cols.end();++it) { if(sub_ntuple* sub = id_cast(*(*it))) { sout << m_spaces << " " << std::endl; sout << sub->value(); sout << m_spaces << " " << std::endl; sub->reset(); } else if(leaf* lf = id_cast(*(*it))){ sout << m_spaces << " s_value().c_str() << "\"/>" << std::endl; } } sout << m_spaces << "" << std::endl; m_tmp += sout.str(); return true; } protected: std::string m_name; std::string m_spaces; std::vector m_cols; std::string m_tmp; }; public: ntuple(std::ostream& a_writer, unsigned int a_spaces = 0) :m_writer(a_writer){ for(unsigned int i=0;i(m_cols); } protected: ntuple(const ntuple& a_from) :m_writer(a_from.m_writer) ,m_spaces(a_from.m_spaces) {} ntuple& operator=(const ntuple& a_from){ m_spaces = a_from.m_spaces; return *this; } public: const std::vector& columns() const {return m_cols;} template column* create_column(const std::string& a_name, const T& a_def = T()) { if(find_named(m_cols,a_name)) return 0; column* col = new column(a_name,a_def); if(!col) return 0; m_cols.push_back(col); return col; } sub_ntuple* create_sub_ntuple(const std::string& a_name){ if(find_named(m_cols,a_name)) return 0; std::string spaces; for(unsigned int i=0;i<10;i++) spaces += " "; sub_ntuple* col = new sub_ntuple(a_name,m_spaces+spaces); if(!col) return 0; m_cols.push_back(col); return col; } void write_header(const std::string& a_path, const std::string& a_name, const std::string& a_title){ // : m_writer << m_spaces << " " << std::endl; // : m_writer << m_spaces << " " << std::endl; std::vector::iterator it; for(it=m_cols.begin();it!=m_cols.end();++it) { if(sub_ntuple* sub = id_cast(*(*it))){ m_writer << m_spaces << " " << std::endl; } else if(leaf* lf = id_cast(*(*it))){ m_writer << m_spaces << " " << std::endl; } } m_writer << m_spaces << " " << std::endl; // rows : m_writer << m_spaces << " " << std::endl; } bool add_row() { if(m_cols.empty()) return false; m_writer << m_spaces << " " << std::endl; std::vector::const_iterator it; for(it=m_cols.begin();it!=m_cols.end();++it) { if(sub_ntuple* sub = id_cast(*(*it))){ m_writer << m_spaces << " " << std::endl; m_writer << sub->value(); m_writer << m_spaces << " " << std::endl; sub->reset(); } else if(leaf* lf = id_cast(*(*it))){ m_writer << m_spaces << " " << std::endl; } } m_writer << m_spaces << " " << std::endl; return true; } void write_trailer() { m_writer << m_spaces << " " << std::endl; m_writer << m_spaces << " " << std::endl; } protected: static void get_booking(const std::vector& a_cols, std::string& a_string) { a_string += "{"; //we need the + because of the tuple in tuple. std::vector::const_iterator it; for(it=a_cols.begin();it!=a_cols.end();++it) { if(it!=a_cols.begin()) a_string += ","; std::string type = (*it)->aida_type(); a_string += type + " "; std::string name = (*it)->name(); a_string += name + " = "; if(sub_ntuple* sub = id_cast(*(*it))){ get_booking(sub->columns(),a_string); } else if(leaf* lf = id_cast(*(*it))){ a_string += lf->s_def(); } } a_string += "}"; } protected: std::ostream& m_writer; std::string m_path; std::string m_name; std::string m_title; std::string m_spaces; std::vector m_cols; }; }} #endif