Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_wcsv_ntuple 5 #define tools_wcsv_ntuple 6 7 // A simple ntuple class to write at the csv format. 8 // (csv = comma separated value). 9 // Each add_row() write a row at the csv format. 10 11 #include "vfind" 12 #include "vmanip" 13 #include <ostream> 14 15 #include "scast" 16 #include "ntuple_booking" 17 #include "sout" 18 //#include "srep" 19 20 namespace tools { 21 namespace wcsv { 22 23 class ntuple { 24 public: 25 static const std::string& s_class() { 26 static const std::string s_v("tools::wcsv::ntuple"); 27 return s_v; 28 } 29 public: 30 class icol { 31 public: 32 virtual ~icol(){} 33 public: 34 virtual void* cast(cid) const = 0; 35 virtual cid id_cls() const = 0; 36 public: 37 virtual void add() = 0; 38 virtual const std::string& name() const = 0; 39 }; 40 41 public: 42 template <class T> 43 class column_ref : public virtual icol { 44 public: 45 static cid id_class() { 46 static const T s_v = T(); //do that for T = std::string. 47 return _cid(s_v)+10000; 48 } 49 virtual void* cast(cid a_class) const { 50 if(void* p = cmp_cast<column_ref>(this,a_class)) {return p;} 51 else return 0; 52 } 53 virtual cid id_cls() const {return id_class();} 54 public: //icol 55 virtual void add() {m_writer << m_ref;} 56 virtual const std::string& name() const {return m_name;} 57 public: 58 column_ref(std::ostream& a_writer,const std::string& a_name,const T& a_ref) 59 :m_writer(a_writer) 60 ,m_name(a_name) 61 ,m_ref(a_ref) 62 {} 63 virtual ~column_ref(){} 64 protected: 65 column_ref(const column_ref& a_from) 66 :icol(a_from) 67 ,m_writer(a_from.m_writer) 68 ,m_name(a_from.m_name) 69 ,m_ref(a_from.m_ref) 70 {} 71 column_ref& operator=(const column_ref& a_from){ 72 m_name = a_from.m_name; 73 return *this; 74 } 75 protected: 76 std::ostream& m_writer; 77 std::string m_name; 78 const T& m_ref; 79 }; 80 81 template <class T> 82 class column : public column_ref<T> { 83 typedef column_ref<T> parent; 84 public: 85 static cid id_class() { 86 static const T s_v = T(); //do that for T = std::string. 87 return _cid(s_v); 88 } 89 virtual void* cast(cid a_class) const { 90 if(void* p = cmp_cast<column>(this,a_class)) {return p;} 91 else return 0; 92 } 93 virtual cid id_cls() const {return id_class();} 94 public: //icol 95 virtual void add() {parent::add();m_tmp = m_def;} 96 public: 97 column(std::ostream& a_writer,const std::string& a_name,const T& a_def) 98 :parent(a_writer,a_name,m_tmp) 99 ,m_def(a_def) 100 ,m_tmp(a_def) 101 {} 102 virtual ~column(){} 103 protected: 104 column(const column& a_from) 105 :icol(a_from) 106 ,parent(a_from) 107 ,m_def(a_from.m_def) 108 ,m_tmp(a_from.m_tmp) 109 {} 110 column& operator=(const column& a_from){ 111 parent::operator=(a_from); 112 m_def = a_from.m_def; 113 m_tmp = a_from.m_tmp; 114 return *this; 115 } 116 public: 117 bool fill(const T& a_value) {m_tmp = a_value;return true;} 118 protected: 119 T m_def; 120 T m_tmp; 121 }; 122 123 /* 124 template <class T> 125 static void escape(T&,const std::string&){} 126 static void escape(std::string& a_s,const std::string& a_sep){ 127 replace(a_s,a_sep,"\\"+a_sep); //if changing here, change rcsv_ntuple/_vec_read() too. 128 } 129 */ 130 131 template <class T> 132 class std_vector_column : public virtual icol { 133 public: 134 static cid id_class() {return _cid_std_vector<T>();} 135 virtual void* cast(cid a_class) const { 136 if(void* p = cmp_cast<std_vector_column>(this,a_class)) {return p;} 137 else return 0; 138 } 139 virtual cid id_cls() const {return id_class();} 140 public: //icol 141 virtual void add() { 142 if(m_ref.empty()) { 143 //m_writer << "none"; 144 } else { 145 //std::string sep;sep+=m_vec_sep; 146 //T value; 147 typedef typename std::vector<T>::const_iterator it_t; 148 for(it_t it=m_ref.begin();it!=m_ref.end();++it) { 149 if(it!=m_ref.begin()) m_writer << m_vec_sep; 150 m_writer << *it; 151 //value = *it;escape(value,sep); 152 //m_writer << value; 153 } 154 } 155 } 156 virtual const std::string& name() const {return m_name;} 157 public: 158 std_vector_column(std::ostream& a_writer,const std::string& a_name,const std::vector<T>& a_ref,char a_vec_sep) 159 :m_writer(a_writer) 160 ,m_name(a_name) 161 ,m_ref(a_ref) 162 ,m_vec_sep(a_vec_sep) 163 {} 164 virtual ~std_vector_column(){} 165 protected: 166 std_vector_column(const std_vector_column& a_from) 167 :icol(a_from) 168 ,m_writer(a_from.m_writer) 169 ,m_name(a_from.m_name) 170 ,m_ref(a_from.m_ref) 171 ,m_vec_sep(a_from.m_vec_sep) 172 {} 173 std_vector_column& operator=(const std_vector_column& a_from){ 174 m_name = a_from.m_name; 175 m_vec_sep = a_from.m_vec_sep; 176 return *this; 177 } 178 protected: 179 std::ostream& m_writer; 180 std::string m_name; 181 const std::vector<T>& m_ref; 182 char m_vec_sep; 183 }; 184 185 public: 186 ntuple(std::ostream& a_writer,char a_sep = ',',char a_vec_sep = ';') 187 :m_writer(a_writer) 188 ,m_sep(a_sep) 189 ,m_vec_sep(a_vec_sep) 190 {} 191 192 ntuple(std::ostream& a_writer, 193 std::ostream& a_out, //for errors. 194 const ntuple_booking& a_bkg, 195 char a_sep = ',',char a_vec_sep = ';') 196 :m_writer(a_writer) 197 ,m_sep(a_sep) 198 ,m_vec_sep(a_vec_sep) 199 ,m_title(a_bkg.title()) 200 { 201 const std::vector<column_booking>& cols = a_bkg.columns(); 202 std::vector<column_booking>::const_iterator it; 203 for(it=cols.begin();it!=cols.end();++it){ 204 205 #define TOOLS_WCSV_NTUPLE_CREATE_COL(a__type) \ 206 if((*it).cls_id()==_cid(a__type())) {\ 207 a__type* user = (a__type*)(*it).user_obj();\ 208 if(user) {\ 209 if(!create_column_ref<a__type>((*it).name(),*user)) {\ 210 a_out << "tools::wcsv_ntuple::wcsv_ntuple : create_column_ref(" << (*it).name() << ") failed." << std::endl;\ 211 safe_clear<icol>(m_cols);\ 212 return;\ 213 }\ 214 } else {\ 215 if(!create_column<a__type>((*it).name())) {\ 216 a_out << "tools::wcsv_ntuple::wcsv_ntuple : create_column(" << (*it).name() << ") failed." << std::endl;\ 217 safe_clear<icol>(m_cols);\ 218 return;\ 219 }\ 220 }\ 221 } 222 223 #define TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(a__type) \ 224 if((*it).cls_id()==_cid_std_vector<a__type>()) {\ 225 std::vector<a__type>* vec = (std::vector<a__type>*)(*it).user_obj();\ 226 if(vec) {\ 227 if(!create_column<a__type>((*it).name(),*vec)) {\ 228 a_out << "tools::wcsv_ntuple::wcsv_ntuple : create_column(" << (*it).name() << ") failed." << std::endl;\ 229 safe_clear<icol>(m_cols);\ 230 return;\ 231 }\ 232 } else {\ 233 a_out << "tools::wcsv_ntuple :"\ 234 << " for std::vector column " << sout((*it).name())\ 235 << ", the user vector pointer is null."\ 236 << std::endl;\ 237 safe_clear<icol>(m_cols);\ 238 return;\ 239 }\ 240 } 241 242 TOOLS_WCSV_NTUPLE_CREATE_COL(char) 243 else TOOLS_WCSV_NTUPLE_CREATE_COL(short) 244 else TOOLS_WCSV_NTUPLE_CREATE_COL(int) 245 else TOOLS_WCSV_NTUPLE_CREATE_COL(int64) 246 247 else TOOLS_WCSV_NTUPLE_CREATE_COL(float) 248 else TOOLS_WCSV_NTUPLE_CREATE_COL(double) 249 250 else TOOLS_WCSV_NTUPLE_CREATE_COL(byte) 251 else TOOLS_WCSV_NTUPLE_CREATE_COL(ushort) 252 else TOOLS_WCSV_NTUPLE_CREATE_COL(uint32) 253 else TOOLS_WCSV_NTUPLE_CREATE_COL(uint64) 254 255 else TOOLS_WCSV_NTUPLE_CREATE_COL(bool) 256 else TOOLS_WCSV_NTUPLE_CREATE_COL(std::string) 257 258 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(char) 259 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(short) 260 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(int) 261 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(int64) 262 263 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(float) 264 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(double) 265 266 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(uchar) 267 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(ushort) 268 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(uint32) 269 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(uint64) 270 271 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(std::string) 272 else TOOLS_WCSV_NTUPLE_CREATE_VEC_COL(bool) 273 274 #undef TOOLS_WCSV_NTUPLE_CREATE_VEC_COL 275 #undef TOOLS_WCSV_NTUPLE_CREATE_COL 276 277 else { 278 a_out << "tools::wcsv::ntuple :" 279 << " for column " << sout((*it).name()) 280 << ", type with cid " << (*it).cls_id() << " not yet handled." 281 << std::endl; 282 //throw 283 safe_clear<icol>(m_cols); 284 return; 285 } 286 } 287 } 288 289 virtual ~ntuple() { 290 safe_clear<icol>(m_cols); 291 } 292 protected: 293 ntuple(const ntuple& a_from) 294 :m_writer(a_from.m_writer) 295 ,m_sep(a_from.m_sep) 296 ,m_vec_sep(a_from.m_vec_sep) 297 ,m_title(a_from.m_title) 298 {} 299 ntuple& operator=(const ntuple& a_from){ 300 m_sep = a_from.m_sep; 301 m_vec_sep = a_from.m_vec_sep; 302 m_title = a_from.m_title; 303 return *this; 304 } 305 public: 306 void write_hippo_header() { 307 m_writer << m_title << std::endl; 308 std::vector<icol*>::const_iterator it; 309 for(it=m_cols.begin();it!=m_cols.end();++it){ 310 if(it!=m_cols.begin()) m_writer << '\t'; 311 m_writer << (*it)->name(); 312 } 313 m_writer << std::endl; 314 } 315 316 bool write_commented_header(std::ostream& a_out) { 317 // commented header similar to the histo case. 318 m_writer << "#class " << s_class() << std::endl; 319 m_writer << "#title " << m_title << std::endl; 320 m_writer << "#separator " << (unsigned int)m_sep << std::endl; 321 m_writer << "#vector_separator " << (unsigned int)m_vec_sep << std::endl; 322 bool status = true; 323 {for(unsigned int count=0;count<m_cols.size();count++) { 324 icol* _col = m_cols[count]; 325 std::string sid; 326 if(!cid2s(_col->id_cls(),sid)) { 327 a_out << "tools::wcsv::ntuple::write_commented_header :" 328 << " unknown column type id " << _col->id_cls() << std::endl; 329 status = false; //but we continue. 330 } else { 331 m_writer << "#column " << sid << " " << _col->name() << std::endl; 332 } 333 }} 334 return status; 335 } 336 337 template <class T> 338 column_ref<T>* create_column_ref(const std::string& a_name,const T& a_ref) { 339 if(find_named<icol>(m_cols,a_name)) return 0; 340 column_ref<T>* col = new column_ref<T>(m_writer,a_name,a_ref); 341 if(!col) return 0; 342 m_cols.push_back(col); 343 return col; 344 } 345 346 template <class T> 347 column<T>* create_column(const std::string& a_name,const T& a_def = T()) { 348 if(find_named<icol>(m_cols,a_name)) return 0; 349 column<T>* col = new column<T>(m_writer,a_name,a_def); 350 if(!col) return 0; 351 m_cols.push_back(col); 352 return col; 353 } 354 355 template <class T> 356 std_vector_column<T>* create_column(const std::string& a_name,const std::vector<T>& a_ref) { 357 //NOTE : to optimize, we do not handle a default std::vector value logic. 358 if(find_named<icol>(m_cols,a_name)) return 0; 359 std_vector_column<T>* col = new std_vector_column<T>(m_writer,a_name,a_ref,m_vec_sep); 360 if(!col) return 0; 361 m_cols.push_back(col); 362 return col; 363 } 364 365 template <class T> 366 column_ref<T>* find_column_ref(const std::string& a_name) { 367 icol* col = find_named<icol>(m_cols,a_name); 368 if(!col) return 0; 369 return id_cast<icol, column_ref<T> >(*col); 370 } 371 372 template <class T> 373 column<T>* find_column(const std::string& a_name) { 374 icol* col = find_named<icol>(m_cols,a_name); 375 if(!col) return 0; 376 return id_cast<icol, column<T> >(*col); 377 } 378 379 bool add_row() { 380 if(m_cols.empty()) return false; 381 std::vector<icol*>::iterator it; 382 it=m_cols.begin(); 383 (*it)->add(); 384 it++; 385 for(;it!=m_cols.end();++it) { 386 m_writer << m_sep; 387 (*it)->add(); 388 } 389 m_writer << std::endl; 390 return true; 391 } 392 393 const std::vector<icol*>& columns() const {return m_cols;} 394 395 void set_title(const std::string& a_value) {m_title = a_value;} 396 const std::string& title() const {return m_title;} 397 protected: 398 std::ostream& m_writer; 399 char m_sep; 400 char m_vec_sep; 401 std::string m_title; 402 std::vector<icol*> m_cols; 403 }; 404 405 }} 406 407 #endif