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