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