Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/rcsv_ntuple is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_rcsv_ntuple
0005 #define tools_rcsv_ntuple
0006 
0007 // A simple ntuple class to read at the csv format.
0008 // (csv = comma separated value).
0009 
0010 // This reader can be use to read file at the hippodraw format
0011 // which is :
0012 // - one header line for the ntuple title.
0013 // - one csv line for column names.
0014 // - data at csv format.
0015 
0016 #include "rntuple"
0017 
0018 #include <istream>
0019 #include <sstream>
0020 
0021 #include "vmanip"
0022 #include "tokenize"
0023 #include "snums"
0024 #include "sto"
0025 #include "s2time"
0026 #include "charmanip"
0027 #include "strip"
0028 #include "cids"
0029 #include "ntuple_binding"
0030 #include "sout"
0031 #include "num2s"
0032 
0033 #include <utility>
0034 
0035 namespace tools {
0036 namespace rcsv {
0037 
0038 class ntuple : public virtual read::intuple {
0039   typedef read::intuple parent;
0040 public: //read::intuple
0041   virtual void start() {
0042     m_reader.clear();
0043     m_reader.seekg(0,std::ios::beg);
0044     if(m_hippo) {
0045       skip_line(m_reader,m_sz);
0046       skip_line(m_reader,m_sz);
0047     }
0048   }
0049   virtual bool next() {
0050     if(!m_sep) return false; //not inited.
0051     if(m_reader.tellg()>=m_sz) return false;
0052     // first time we are at bol but else we are at eol.
0053     char c;
0054     m_reader.get(c);
0055     if(c==LF()){
0056       if(m_reader.tellg()>=m_sz) {
0057         //eof. Tell caller to stop looping on ntuple rows.
0058         return false;
0059       }
0060       //eol. Next char read is going to be at bol.
0061     } else {
0062       m_reader.putback(c);
0063       //bol
0064     }
0065     // ready for a new row :
0066 
0067     while(skip_comment(m_reader,m_sz)){}
0068     if(m_reader.tellg()>=m_sz) return false;
0069 
0070     return _read_line();
0071   }
0072 
0073   virtual read::icol* find_icol(const std::string& a_name){
0074     return find_named<read::icol>(m_cols,a_name);
0075   }
0076 
0077   virtual const std::vector<read::icol*>& columns() const {return m_cols;}
0078 
0079   virtual const std::string& title() const {return m_title;}
0080 
0081   virtual bool number_of_entries(tools::uint64 & a_value) const {
0082     if(!m_sep) {a_value = 0;return false;} //not inited.
0083     ntuple& self = const_cast<ntuple&>(*this);
0084     if(m_rows==(-1)) {
0085       self.m_rows = 0;
0086       self.start();
0087       while(self.next()) {self.m_rows++;}
0088     }
0089     a_value = (uint64)m_rows;
0090     return true;
0091   }
0092 public:
0093   template <class T>
0094   class column : public virtual read::icolumn<T> {
0095     typedef read::icolumn<T> parent;
0096   public:
0097     static cid id_class() {
0098       static const T s_v = T(); //do that for T = std::string.
0099       return 200+_cid(s_v);
0100     }
0101   public: //icol
0102     virtual void* cast(cid a_class) const {
0103       if(void* p = cmp_cast<column>(this,a_class)) {return p;}
0104       return parent::cast(a_class);
0105     }
0106     virtual cid id_cls() const {return id_class();}
0107   public: //icol
0108     virtual const std::string& name() const {return m_name;}
0109     virtual bool fetch_entry() const {
0110       if(m_user_var) *m_user_var = m_tmp;
0111       return true;
0112     }
0113   public: //icolumn<T>
0114     virtual bool get_entry(T& a_v) const {
0115       a_v = m_tmp;
0116       return true;
0117     }
0118   public:
0119     column(const std::string& a_name,T* a_user_var = 0)
0120     :m_name(a_name)
0121     ,m_tmp(T())
0122     ,m_user_var(a_user_var) //not owner
0123     {}
0124     virtual ~column(){}
0125   protected:
0126     column(const column& a_from)
0127     :read::icol(a_from)
0128     ,parent(a_from)
0129     ,m_name(a_from.m_name)
0130     ,m_tmp(a_from.m_tmp)
0131     ,m_user_var(a_from.m_user_var)
0132     {}
0133     column& operator=(const column& a_from){
0134       m_name = a_from.m_name;
0135       m_tmp = a_from.m_tmp;
0136       m_user_var = a_from.m_user_var;
0137       return *this;
0138     }
0139   public:
0140     // should be used in ntuple _read_line only :
0141     void set_value(const T& a_v){m_tmp = a_v;}
0142   protected:
0143     std::string m_name;
0144     T m_tmp;
0145     T* m_user_var;
0146   };
0147 
0148 public:
0149   ntuple(std::istream& a_reader)
0150   :m_reader(a_reader)
0151   ,m_title()
0152   ,m_sep(0)
0153   ,m_vec_sep(';')
0154   ,m_sz(0)
0155   ,m_rows(-1)
0156   ,m_hippo(false)
0157   {
0158   }
0159   virtual ~ntuple() {
0160     safe_clear<read::icol>(m_cols);
0161   }
0162 protected:
0163   ntuple(const ntuple& a_from)
0164   :parent(a_from)
0165   ,m_reader(a_from.m_reader)
0166   ,m_title(a_from.m_title)
0167   ,m_sep(a_from.m_sep)
0168   ,m_vec_sep(a_from.m_vec_sep)
0169   ,m_sz(a_from.m_sz)
0170   ,m_rows(-1)
0171   ,m_hippo(a_from.m_hippo)
0172   {
0173   }
0174   ntuple& operator=(const ntuple& a_from){
0175     m_title = a_from.m_title;
0176     m_sep = a_from.m_sep;
0177     m_vec_sep = a_from.m_vec_sep;
0178     m_hippo = a_from.m_hippo;
0179     m_rows = a_from.m_rows;
0180     return *this;
0181   }
0182 public:
0183   void set_vec_sep(char a_c) {m_vec_sep = a_c;}
0184   void set_sep(char a_c) {m_sep = a_c;}
0185   void set_hippo(bool a_hippo) {m_hippo = a_hippo;}
0186 
0187   std::istream& istrm() {return m_reader;}
0188 
0189   static bool find_sep(std::ostream& a_out,
0190                        std::istream& a_reader,bool a_hippo,
0191                        bool a_verbose,
0192                        char& a_sep){
0193     // analyse first data line to find the char separator.
0194 
0195     a_reader.clear();
0196     a_reader.seekg(0,std::ios::end);
0197     std::streampos sz = a_reader.tellg();
0198     a_reader.seekg(0,std::ios::beg);
0199     if(!sz) {
0200       a_out << "tools::rcsv::ntuple::find_sep :"
0201             << " stream is empty."
0202             << std::endl;
0203       a_sep = 0;
0204       return false;
0205     } //file empty.
0206     if(a_verbose) a_out << "file size " << sz << std::endl;
0207 
0208     if(a_hippo) { //skip first two lines :
0209       if(!skip_line(a_reader,sz)) {a_sep = 0;return false;}
0210       if(!skip_line(a_reader,sz)) {a_sep = 0;return false;}
0211     } else {
0212       while(skip_comment(a_reader,sz)){}
0213     }
0214     if(a_reader.tellg()>=sz) {a_sep=0;return false;} //no data line.
0215 
0216     // get first data line :
0217     std::string sfirst;
0218    {char c;
0219     while(true) {
0220       if(a_reader.tellg()>=sz) break;
0221       a_reader.get(c);
0222       if((c==CR())||(c==LF())) break;
0223       sfirst += c;
0224     }}
0225     if(sfirst.empty()) {
0226       a_out << "tools::rcsv::ntuple::find_set :"
0227             << " first datat line is empty."
0228             << std::endl;
0229       a_sep = 0;
0230       return false;
0231     }
0232     if(a_verbose) a_out << "first data line \"" << sfirst << "\"" << std::endl;
0233 
0234     //guess sep from first data line :
0235     std::istringstream strm(sfirst.c_str());
0236     double d;
0237     strm >> d;
0238     std::streampos pos = strm.tellg();
0239     if(pos==std::streampos(-1)) {
0240       a_out << "tools::rcsv::ntuple::find_sep :"
0241             << " first line does not start with a number."
0242             << std::endl;
0243       a_sep = 0;
0244       return false;
0245     } //not a number.
0246     if(a_verbose) a_out << "first number " << d
0247                         << " ending at pos " << pos << std::endl;
0248     if(pos>=(std::streampos)sfirst.size()) {
0249       a_out << "tools::rcsv::ntuple::find_sep :"
0250             << " no separator found in first line."
0251             << " pos " << pos
0252             << " sfirst.size() " << sfirst.size()
0253             << std::endl;
0254       a_sep = 0;
0255       return false;
0256     } //no sep.
0257 
0258     strm.get(a_sep);
0259 
0260     return true;
0261   }
0262 
0263 public:
0264   bool initialize(std::ostream& a_out,
0265                   char a_sep = 0, //guessed
0266                   const std::string& a_suffix = "x", //col suffix
0267                   bool a_verbose = false) {
0268     safe_clear<read::icol>(m_cols);
0269     m_sep = 0;
0270     m_sz = 0;
0271     m_rows = -1;
0272 
0273     if(a_suffix.empty()) {
0274       a_out << "tools::rcsv::ntuple::initialize : expect a column suffix." << std::endl;
0275       return false;
0276     }
0277 
0278     m_reader.clear();
0279     m_reader.seekg(0,std::ios::end);
0280     m_sz = m_reader.tellg();
0281     m_reader.seekg(0,std::ios::beg);
0282     if(!m_sz) {
0283       a_out << "tools::rcsv::ntuple::initialize :"
0284             << " stream is empty."
0285             << std::endl;
0286       return false; //file empty.
0287     }
0288     if(a_verbose) a_out << "file size " << m_sz << std::endl;
0289 
0290     std::vector<std::string> labels;
0291     if(m_hippo) { //skip first two lines :
0292       std::string _title;
0293       if(!read_line(m_reader,m_sz,_title)) {
0294         a_out << "tools::rcsv::ntuple::initialize : read_line() failed." << std::endl;
0295         m_sz = 0;
0296         m_rows = -1;
0297         return false;
0298       }
0299       std::string _s;
0300       if(!read_line(m_reader,m_sz,_s)) {
0301         a_out << "tools::rcsv::ntuple::initialize : (2) read_line() failed." << std::endl;
0302         m_sz = 0;
0303         m_rows = -1;
0304         return false;
0305       }
0306       words(_s,"\t",false,labels); //false for glast.tnt that has a trailing \t.
0307     } else {
0308       while(skip_comment(m_reader,m_sz)){}
0309     }
0310     if(m_reader.tellg()>=m_sz) {
0311       a_out << "tools::rcsv::ntuple::initialize : tellg() >= sz." << std::endl;
0312       m_sz = 0;
0313       m_rows = -1;
0314       return false;
0315     }
0316 
0317     // get first data line :
0318     std::string sfirst;
0319   {{char c;
0320     while(true) {
0321       if(m_reader.tellg()>=m_sz) break;
0322       m_reader.get(c);
0323       if((c==CR())||(c==LF())) break;
0324       sfirst += c;
0325     }}
0326     if(sfirst.empty()) {
0327       a_out << "tools::rcsv::ntuple::initialize :"
0328             << " first datat line is empty."
0329             << std::endl;
0330       m_sz = 0;
0331       m_rows = -1;
0332       return false;
0333     }}
0334     if(a_verbose) a_out << "first data line \"" << sfirst << "\"" << std::endl;
0335 
0336     if(a_sep) {
0337       m_sep = a_sep;
0338     } else {
0339       //guess sep from first data line :
0340       std::istringstream strm(sfirst.c_str());
0341       double d;
0342       strm >> d;
0343       std::streampos pos = strm.tellg();
0344       if(pos==std::streampos(-1)) {
0345         a_out << "tools::rcsv::ntuple::initialize :"
0346               << " first line does not start with a number."
0347               << std::endl;
0348         m_sz = 0;
0349         m_rows = -1;
0350         return false;
0351       }
0352       if(a_verbose) a_out << "first number " << d << " ending at pos " << pos << std::endl;
0353       if(pos>=(std::streampos)sfirst.size()) {
0354         a_out << "tools::rcsv::ntuple::initialize :"
0355               << " no separator found in first line."
0356               << std::endl;
0357         m_sz = 0;
0358         m_rows = -1;
0359         return false;
0360       }
0361       strm.get(m_sep);
0362     }
0363     if(a_verbose) a_out << "sep " << (int)m_sep << std::endl;
0364 
0365     // in case sep is ' ', there is an ambiguity with some leading
0366     // space in front of first number.
0367     if(m_sep==' ') strip(sfirst,leading,' ');
0368 
0369     std::vector<std::string> ws;
0370    {std::string sep;
0371     sep += m_sep;
0372     words(sfirst,sep,m_hippo?false:true,ws);}
0373 
0374     // look if words are numbers :
0375     if(a_verbose) a_out << "words " << ws.size() << std::endl;
0376     unsigned int index = 0;
0377     std::vector<std::string>::iterator it;
0378     for(it=ws.begin();it!=ws.end();++it,index++) {
0379       if(a_verbose) a_out << "word " << sout(*it) << "" << std::endl;
0380       std::string name = a_suffix;
0381       if(!numas<uint64>(m_cols.size(),name)){}
0382       if(m_hippo) {
0383         if(index>=labels.size()) {
0384           a_out << "tools::rcsv::ntuple::initialize :"
0385                 << " warning : not enough labels."
0386                 << std::endl;
0387         } else {
0388           name = labels[index];
0389         }
0390       }
0391       double d;
0392       if(to<double>(*it,d)) {
0393         if(a_verbose) a_out << "number " << d << std::endl;
0394         create_column<double>(name);
0395       } else {
0396         time_t time;
0397         if(s2time(*it,time)) {
0398           create_column<csv_time>(name);
0399         } else {
0400           std::vector<double> v;
0401           std::string vec_sep;vec_sep += m_vec_sep;
0402           if(snums<double>(*it,vec_sep,v)&&v.size()) {
0403             create_column< std::vector<double> >(name);
0404           } else {
0405             create_column<std::string>(name);
0406           }
0407         }
0408       }
0409     }
0410 
0411     size_t num = m_cols.size();
0412     if(!num) {
0413       a_out << "tools::rcsv::ntuple::initialize :"
0414             << " zero columns."
0415             << std::endl;
0416       m_sep = 0;
0417       m_sz = 0;
0418       m_rows = -1;
0419       return false;
0420     }
0421 
0422     return true;
0423   }
0424 
0425   static const std::string& s_cid(cid a_id) {
0426 
0427 #define TOOLS_RCSV_NTUPLE_IF_CID(a__name,a__type) \
0428     if(a_id==column<a__type>::id_class()) {\
0429       static const std::string s_v(#a__name);\
0430       return s_v;\
0431     }
0432 
0433 #define TOOLS_RCSV_NTUPLE_IF_VEC_CID(a__name,a__type) \
0434     if(a_id==column< std::vector<a__type> >::id_class()) {\
0435       static const std::string s_v(#a__name+std::string("[]"));\
0436       return s_v;\
0437     }
0438 
0439          TOOLS_RCSV_NTUPLE_IF_CID(char,char)
0440     else TOOLS_RCSV_NTUPLE_IF_CID(short,short)
0441     else TOOLS_RCSV_NTUPLE_IF_CID(int,int)
0442     else TOOLS_RCSV_NTUPLE_IF_CID(int64,int64)
0443 
0444     else TOOLS_RCSV_NTUPLE_IF_CID(float,float)
0445     else TOOLS_RCSV_NTUPLE_IF_CID(double,double)
0446 
0447     else TOOLS_RCSV_NTUPLE_IF_CID(uchar,uchar)
0448     else TOOLS_RCSV_NTUPLE_IF_CID(ushort,ushort)
0449     else TOOLS_RCSV_NTUPLE_IF_CID(uint,uint32)   //WARNING
0450     else TOOLS_RCSV_NTUPLE_IF_CID(uint64,uint64)
0451 
0452     else TOOLS_RCSV_NTUPLE_IF_CID(bool,bool)
0453     else if(a_id==column<std::string>::id_class()) {
0454       static const std::string s_v("string");
0455       return s_v;
0456     }
0457 
0458     else if(a_id==column<csv_time>::id_class()) {
0459       static const std::string s_v("time");
0460       return s_v;
0461     }
0462 
0463     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(char,char)
0464     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(short,short)
0465     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(int,int)
0466     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(int64,int64)
0467 
0468     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(float,float)
0469     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(double,double)
0470 
0471     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(uchar,uchar)
0472     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(ushort,ushort)
0473     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(uint,uint32)   //WARNING
0474     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(uint64,uint64)
0475 
0476     else TOOLS_RCSV_NTUPLE_IF_VEC_CID(bool,bool)
0477     else if(a_id==column< std::vector<std::string> >::id_class()) {
0478       static const std::string s_v("string[]");
0479       return s_v;
0480     }
0481 
0482 #undef TOOLS_RCSV_NTUPLE_IF_CID
0483 #undef TOOLS_RCSV_NTUPLE_IF_VEC_CID
0484 
0485     else {
0486       static const std::string s_v("unknown");
0487       return s_v;
0488     }
0489   }
0490 
0491   void dump_columns(std::ostream& a_out) const {
0492     if((m_sep>=32)&&(m_sep<=126)) { //printable
0493       a_out << "separator is '" << m_sep << "'" << std::endl;
0494     } else {
0495       a_out << "separator is " << (unsigned int)m_sep << std::endl;
0496     }
0497     a_out << "number of columns " << m_cols.size() << std::endl;
0498     std::vector<read::icol*>::const_iterator it;
0499     for(it=m_cols.begin();it!=m_cols.end();++it) {
0500       a_out << sout((*it)->name())
0501             << " " << s_cid((*it)->id_cls())
0502             << std::endl;
0503     }
0504   }
0505 public:
0506   typedef std::pair<std::string,std::string> col_desc;
0507 
0508   bool initialize(std::ostream& a_out,const ntuple_binding& a_bd = ntuple_binding()) {
0509     // it assumes a "commented header".
0510 
0511     safe_clear<read::icol>(m_cols);
0512     m_sep = 0;
0513     m_sz = 0;
0514     m_rows = -1;
0515     m_hippo = false;
0516 
0517     m_reader.clear();
0518     m_reader.seekg(0,std::ios::end);
0519     m_sz = m_reader.tellg();
0520     m_reader.seekg(0,std::ios::beg);
0521     if(!m_sz) {
0522       a_out << "tools::rcsv::ntuple::initialize(booking) :"
0523             << " stream is empty."
0524             << std::endl;
0525       return false; //file empty.
0526     }
0527 
0528     std::string _title;
0529     char _sep,_vec_sep;
0530     std::vector<col_desc> _cols;
0531     if(!read_commented_header(a_out,m_reader,_title,_sep,_vec_sep,_cols)) return false;
0532 
0533     m_sep = _sep;
0534     m_title = std::move(_title);
0535 
0536     tools_vforcit(col_desc,_cols,it) {
0537       const std::string& type = (*it).first;
0538       const std::string& name = (*it).second;
0539 
0540 #define TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(a__name,a__type) \
0541       if(type==(std::string(#a__name)+"[]")) {\
0542         create_column< std::vector<a__type> >(name,a_bd.find_variable< std::vector<a__type> >(name));\
0543       }
0544 
0545       // see cid2s() for string types.
0546 
0547            if(type=="char")   create_column<char>(name,a_bd.find_variable<char>(name));
0548       else if(type=="short")  create_column<short>(name,a_bd.find_variable<short>(name));
0549       else if(type=="int")    create_column<int>(name,a_bd.find_variable<int>(name));
0550       else if(type=="float")  create_column<float>(name,a_bd.find_variable<float>(name));
0551       else if(type=="double") create_column<double>(name,a_bd.find_variable<double>(name));
0552       else if(type=="string") create_column<std::string>(name,a_bd.find_variable<std::string>(name));
0553 
0554       else if(type=="uchar")  create_column<unsigned char>(name,a_bd.find_variable<unsigned char>(name));
0555       else if(type=="ushort") create_column<unsigned short>(name,a_bd.find_variable<unsigned short>(name));
0556       else if(type=="uint")   create_column<uint32>(name,a_bd.find_variable<uint32>(name)); //WARNING
0557       else if(type=="bool")   create_column<bool>(name,a_bd.find_variable<bool>(name));
0558       else if(type=="int64")  create_column<int64>(name,a_bd.find_variable<int64>(name));
0559       else if(type=="uint64") create_column<uint64>(name,a_bd.find_variable<uint64>(name));
0560 
0561       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(char,char)
0562       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(short,short)
0563       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(int,int)
0564       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(float,float)
0565       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(double,double)
0566 
0567       else if(type=="string[]") create_column< std::vector<std::string> >(name,a_bd.find_variable< std::vector<std::string> >(name));
0568 
0569       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(uchar,uchar)
0570       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(ushort,ushort)
0571       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(uint,uint32)   //WARNING
0572       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(bool,bool)
0573       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(int64,int64)
0574       else TOOLS_RCSV_NTUPLE_CREATE_VEC_COL(uint64,uint64)
0575 
0576       else {
0577         a_out << "tools::rcsv::ntuple::initialize(booking) :"
0578               << " unhandled column type " << sout(type)
0579               << std::endl;
0580         safe_clear<read::icol>(m_cols);
0581         m_sep = 0;
0582         m_sz = 0;
0583         m_rows = -1;
0584         m_hippo = false;
0585         return false;
0586       }
0587 
0588 #undef TOOLS_RCSV_NTUPLE_CREATE_VEC_COL
0589 
0590     }
0591 
0592     size_t num = m_cols.size();
0593     if(!num) {
0594       a_out << "tools::rcsv::ntuple::initialize(booking) :"
0595             << " zero columns."
0596             << std::endl;
0597       m_sep = 0;
0598       m_sz = 0;
0599       m_rows = -1;
0600       m_hippo = false;
0601       return false;
0602     }
0603 
0604    {tools_vforcit(column_binding,a_bd.columns(),it) {
0605       if(!find_named<read::icol>(m_cols,(*it).name())) {
0606         a_out << "tools::rcsv::ntuple::initialize :"
0607               << " error : for column binding with name " << sout((*it).name()) << ", no ntuple column found."
0608               << std::endl;
0609         safe_clear<read::icol>(m_cols);
0610         m_sep = 0;
0611         m_sz = 0;
0612         m_rows = -1;
0613         m_hippo = false;
0614         return false;
0615       }
0616     }}
0617 
0618     return true;
0619   }
0620 
0621   bool initialize_from_commented_header(std::ostream& a_out) { // it assumes a "commented header".
0622     std::string _title;
0623     char _sep,_vec_sep;
0624     std::vector<col_desc> _cols;
0625     if(!read_commented_header(a_out,m_reader,_title,_sep,_vec_sep,_cols)) return false;
0626     ntuple_binding nbd;
0627    {tools_vforcit(col_desc,_cols,it) nbd.add_column_no_var((*it).second);} //user_var is 0.
0628     return initialize(a_out,nbd);
0629   }
0630 
0631   bool get_row() const {
0632     bool status = true;
0633     tools_vforcit(read::icol*,m_cols,it) {
0634       if(!(*it)->fetch_entry()) status = false;
0635     }
0636     return status;
0637   }
0638 
0639 protected:
0640   bool read_commented_header(std::ostream& a_out,std::istream& a_reader,
0641                              std::string& a_title,char& a_sep,char& a_vec_sep,std::vector<col_desc>& a_cols) {
0642     // analyse first lines starting with '#'.
0643     a_title.clear();
0644     a_sep = 0;
0645     a_cols.clear();
0646 
0647     a_reader.clear();
0648     a_reader.seekg(0,std::ios::end);
0649     std::streampos sz = a_reader.tellg();
0650     a_reader.seekg(0,std::ios::beg);
0651     if(!sz) {
0652       a_out << "tools::rcsv::ntuple::read_commented_header :"
0653             << " stream is empty."
0654             << std::endl;
0655       return false;
0656     } //file empty.
0657 
0658 
0659     std::string _class;
0660 
0661     while(true) {
0662       if(a_reader.tellg()>=sz) break;
0663       //we should be at bol :
0664       char c;
0665       a_reader.get(c);
0666       a_reader.putback(c);
0667       if(c!='#') break; //finished, probably a data line now.
0668       std::string line;
0669       if(!read_line(a_reader,sz,line)) break; //or return false ?
0670 
0671       std::vector<std::string> _words;
0672       words(line," ",false,_words);
0673       if(!_words.size()) {
0674         a_out << "tools::rcsv::ntuple::read_commented_header :"
0675               << " syntax error : empty header line."
0676               << std::endl;
0677         return false;
0678       }
0679       if((_words[0]=="#class")) {
0680         if(_words.size()!=2) {
0681           a_out << "tools::rcsv::ntuple::read_commented_header :"
0682                 << " syntax error in " << sout(line)
0683                 << std::endl;
0684           return false;
0685         }
0686         _class = _words[1];
0687       } else if(_words[0]=="#title") {
0688         if(_words.size()<1) {
0689           a_out << "tools::rcsv::ntuple::read_commented_header :"
0690                 << " syntax error in " << sout(line)
0691                 << std::endl;
0692           return false;
0693         }
0694         if(_words.size()==1)  {
0695           a_title.clear();
0696         } else {
0697           std::string::size_type pos = line.find(_words[0]);
0698           pos += _words[0].size()+1;
0699           a_title = line.substr(pos,line.size()-pos);
0700         }
0701       } else if((_words[0]=="#separator")) {
0702         if(_words.size()!=2) {
0703           a_out << "tools::rcsv::ntuple::read_commented_header :"
0704                 << " syntax error in " << sout(line)
0705                 << std::endl;
0706           return false;
0707         }
0708         unsigned int uisep;
0709         if(!to(_words[1],uisep)) {
0710           a_out << "tools::rcsv::ntuple::read_commented_header :"
0711                 << " syntax error in " << sout(line)
0712                 << std::endl;
0713           return false;
0714         }
0715         a_sep = (char)uisep;
0716       } else if((_words[0]=="#vector_separator")) {
0717         if(_words.size()!=2) {
0718           a_out << "tools::rcsv::ntuple::read_commented_header :"
0719                 << " syntax error in " << sout(line)
0720                 << std::endl;
0721           return false;
0722         }
0723         unsigned int uisep;
0724         if(!to(_words[1],uisep)) {
0725           a_out << "tools::rcsv::ntuple::read_commented_header :"
0726                 << " syntax error in " << sout(line)
0727                 << std::endl;
0728           return false;
0729         }
0730         a_vec_sep = (char)uisep;
0731       } else if((_words[0]=="#column")) {
0732         if(_words.size()<2) {
0733           a_out << "tools::rcsv::ntuple::read_commented_header :"
0734                 << " syntax error in " << sout(line)
0735                 << std::endl;
0736           return false;
0737         }
0738         std::string stype = _words[1];
0739         std::string label;
0740         if(_words.size()==2) {
0741           label.clear();
0742         } else {
0743           std::string::size_type pos = line.find(_words[1]);
0744           pos += _words[1].size()+1;
0745           label = line.substr(pos,line.size()-pos);
0746         }
0747         //a_out << "column " << stype << " " << sout(label) << std::endl;
0748         a_cols.push_back(col_desc(stype,label));
0749       } else {
0750         a_out << "tools::rcsv::ntuple::read_commented_header :"
0751               << " syntax error in " << sout(line)
0752               << ", unknown keyword " << sout(_words[0])
0753               << std::endl;
0754       }
0755     }
0756 
0757     return true;
0758   }
0759 
0760 protected:
0761   template <class T>
0762   column<T>* create_column(const std::string& a_name,T* a_user_var = 0){
0763     if(find_named<read::icol>(m_cols,a_name)) return 0;
0764     column<T>* col = new column<T>(a_name,a_user_var);
0765     if(!col) return 0;
0766     m_cols.push_back(col);
0767     return col;
0768   }
0769 
0770 protected:
0771   static bool read_line(std::istream& a_reader,std::streampos a_sz,std::string& a_s){
0772     a_s.clear();
0773     char c;
0774     while(true) {
0775       if(a_reader.tellg()>=a_sz) {a_s.clear();return false;}
0776       a_reader.get(c);
0777       if(c==CR()) continue;
0778       if(c==LF()) break; //eol.
0779       a_s += c;
0780     }
0781     return true;
0782   }
0783 
0784   static bool skip_line(std::istream& a_reader,std::streampos a_sz){
0785     char c;
0786     while(true) {
0787       if(a_reader.tellg()>=a_sz) return false;
0788       a_reader.get(c);
0789       if(c==LF()) break;
0790     }
0791     return true;
0792   }
0793 
0794   static bool skip_comment(std::istream& a_reader,std::streampos a_sz){
0795     //ret true = we had a commented line, false : a data line or nothing.
0796     if(a_reader.tellg()>=a_sz) return false;
0797     //we should be at bol :
0798     char c;
0799     a_reader.get(c);
0800     if(c=='#') {
0801       return skip_line(a_reader,a_sz);
0802       //eol. Next char should be bol.
0803     } else {
0804       a_reader.putback(c);
0805       return false;
0806     }
0807   }
0808 
0809   template <class T>
0810   static bool _read(std::istream& a_reader,std::streampos,char,T& a_v) {
0811     a_reader >> a_v;
0812     if(a_reader.tellg()==std::streampos(-1)) {a_v = 0;return false;}
0813     return true;
0814   }
0815   static bool _read_time(std::istream& a_reader,std::streampos a_sz,char a_sep,time_t& a_v) {
0816     std::string _s;
0817     char c;
0818     while(true){
0819       if(a_reader.tellg()>=a_sz) break;
0820       a_reader.get(c);
0821       if((c==a_sep)||(c==CR())||(c==LF())) {
0822         a_reader.putback(c);
0823         break;
0824       }
0825       _s += c;
0826     }
0827     if(!s2time(_s,a_v)) return false;
0828     return true;
0829   }
0830   static bool _read(std::istream& a_reader,std::streampos a_sz,char a_sep,std::string& a_v) {
0831     a_v.clear();
0832     char c;
0833     while(true){
0834       if(a_reader.tellg()>=a_sz) break;
0835       a_reader.get(c);
0836       if((c==a_sep)||(c==CR())||(c==LF())) {
0837         a_reader.putback(c);
0838         break;
0839       }
0840       a_v += c;
0841     }
0842     return true;
0843   }
0844 
0845   static bool _vec_read(std::istream& a_reader,std::streampos a_sz,
0846                         std::istringstream&,std::vector<std::string>&,
0847                         char a_sep,const std::string& a_vec_sep,
0848                         std::vector<std::string>& a_v) {
0849     std::string _s;
0850     if(!_read(a_reader,a_sz,a_sep,_s)) return false;
0851     words(_s,a_vec_sep,true,a_v);
0852     return true;
0853   }
0854 
0855   template <class T>
0856   static bool _vec_read(std::istream& a_reader,std::streampos a_sz,
0857                         std::istringstream& a_iss,std::vector<std::string>& a_tmp,
0858                         char a_sep,const std::string& a_vec_sep,
0859                         std::vector<T>& a_v) {
0860     std::string _s;
0861     if(!_read(a_reader,a_sz,a_sep,_s)) return false;
0862     if(!snums<T>(_s,a_iss,a_tmp,a_vec_sep,a_v)) return false;
0863     return true;
0864   }
0865 
0866 protected:
0867   bool _read_line() {
0868     // have to loop on all columns !
0869     typedef read::icol icol_t;
0870 
0871     typedef ntuple::column<char> col_char;
0872     typedef ntuple::column<short> col_short;
0873     typedef ntuple::column<int> col_int;
0874     typedef ntuple::column<float> col_float;
0875     typedef ntuple::column<double> col_double;
0876     typedef std::string string_t;
0877     typedef ntuple::column<string_t> col_string_t;
0878 
0879     typedef ntuple::column<uchar> col_uchar;
0880     typedef ntuple::column<ushort> col_ushort;
0881     typedef ntuple::column<uint32> col_uint32;
0882     typedef ntuple::column<bool> col_bool;
0883     typedef ntuple::column<int64> col_int64;
0884     typedef ntuple::column<uint64> col_uint64;
0885 
0886     typedef ntuple::column<csv_time> col_time;
0887 
0888     typedef ntuple::column< std::vector<char> > col_vec_char;
0889     typedef ntuple::column< std::vector<short> > col_vec_short;
0890     typedef ntuple::column< std::vector<int32> > col_vec_int;
0891     typedef ntuple::column< std::vector<float> > col_vec_float;
0892     typedef ntuple::column< std::vector<double> > col_vec_double;
0893     typedef ntuple::column< std::vector<std::string> > col_vec_string_t;
0894 
0895     typedef ntuple::column< std::vector<uchar> > col_vec_uchar;
0896     typedef ntuple::column< std::vector<ushort> > col_vec_ushort;
0897     typedef ntuple::column< std::vector<uint32> > col_vec_uint32;
0898     typedef ntuple::column< std::vector<bool> > col_vec_bool;
0899     typedef ntuple::column< std::vector<int64> > col_vec_int64;
0900     typedef ntuple::column< std::vector<uint64> > col_vec_uint64;
0901 
0902     std::string vec_sep;vec_sep += m_vec_sep;
0903     std::istringstream iss;
0904     std::vector<std::string> tmp;
0905 
0906     size_t index = 0;
0907     size_t num = m_cols.size();
0908     std::vector<icol_t*>::const_iterator it;
0909     for(it=m_cols.begin();it!=m_cols.end();++it,index++) {
0910 
0911 #define TOOLS_RCSV_NTUPLE_IF_COL(a__type) \
0912       if(col_##a__type* _col_##a__type = id_cast<icol_t,col_##a__type>(*(*it))) {\
0913         a__type v;\
0914         if(!_read(m_reader,m_sz,m_sep,v)) return false;\
0915         _col_##a__type->set_value(v);\
0916       }
0917 
0918 #define TOOLS_RCSV_NTUPLE_IF_VEC_COL(a__type) \
0919       if(col_vec_##a__type* _col_vec_##a__type = id_cast<icol_t,col_vec_##a__type>(*(*it))) {\
0920         std::vector<a__type> v;\
0921         if(!_vec_read(m_reader,m_sz,iss,tmp,m_sep,vec_sep,v)) return false;\
0922         _col_vec_##a__type->set_value(v);\
0923       }
0924 
0925            TOOLS_RCSV_NTUPLE_IF_COL(char)
0926       else TOOLS_RCSV_NTUPLE_IF_COL(short)
0927       else TOOLS_RCSV_NTUPLE_IF_COL(int)
0928       else TOOLS_RCSV_NTUPLE_IF_COL(float)
0929       else TOOLS_RCSV_NTUPLE_IF_COL(double)
0930       else TOOLS_RCSV_NTUPLE_IF_COL(string_t)
0931 
0932       else TOOLS_RCSV_NTUPLE_IF_COL(uchar)
0933       else TOOLS_RCSV_NTUPLE_IF_COL(ushort)
0934       else TOOLS_RCSV_NTUPLE_IF_COL(uint32)
0935       else TOOLS_RCSV_NTUPLE_IF_COL(bool)
0936       else TOOLS_RCSV_NTUPLE_IF_COL(int64)
0937       else TOOLS_RCSV_NTUPLE_IF_COL(uint64)
0938 
0939       else if(col_time* _col_time = id_cast<icol_t,col_time>(*(*it))) {
0940         time_t v;
0941         if(!_read_time(m_reader,m_sz,m_sep,v)) return false;
0942         csv_time ct;ct.m_l = long(v);
0943         _col_time->set_value(ct);
0944       }
0945 
0946       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(char)
0947       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(short)
0948       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(int)
0949       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(float)
0950       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(double)
0951       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(string_t)
0952 
0953       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(uchar)
0954       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(ushort)
0955       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(uint32)
0956       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(bool)
0957       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(int64)
0958       else TOOLS_RCSV_NTUPLE_IF_VEC_COL(uint64)
0959 
0960 #undef TOOLS_RCSV_NTUPLE_IF_COL
0961 #undef TOOLS_RCSV_NTUPLE_IF_VEC_COL
0962 
0963       else {
0964         return false;
0965       }
0966 
0967       if(index==(num-1)) { //read up to LF()
0968         char c;
0969         while(true){
0970           if(m_reader.tellg()>=m_sz) break;
0971           m_reader.get(c);
0972           if(c==LF()) break;
0973         }
0974       } else { //read sep :
0975         char sep;
0976         m_reader.get(sep);
0977       }
0978     }
0979     return true;
0980   }
0981 protected:
0982   std::istream& m_reader;
0983   std::string m_title;
0984   char m_sep;
0985   char m_vec_sep;
0986   std::vector<read::icol*> m_cols;
0987   std::streampos m_sz;
0988   int m_rows; //to optimize number_of_entries().
0989   bool m_hippo;
0990 };
0991 
0992 }}
0993 
0994 #endif