Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_waxml_ntuple 5 #define tools_waxml_ntuple 6 7 // A ntuple class to write at the aida tuple format. 8 // Each add_row() write a row at the aida tuple format. 9 10 #include "../vfind" 11 #include "../vmanip" 12 #include "../sout" 13 #include "../srep" 14 #include "../tos" 15 #include "../forit" 16 17 #include <ostream> 18 19 // for sub_ntuple : 20 #include "../scast" 21 #include <sstream> 22 23 #include "../ntuple_booking" 24 25 namespace tools { 26 namespace waxml { 27 28 class ntuple { 29 protected: 30 31 class iobj { 32 public: 33 virtual ~iobj(){} 34 public: 35 virtual void* cast(cid) const = 0; 36 virtual cid id_cls() const = 0; 37 public: 38 virtual const std::string& name() const = 0; 39 virtual const std::string& aida_type() const = 0; 40 }; 41 42 class leaf : public virtual iobj { 43 public: 44 static cid id_class() {return 100;} 45 public: //iobj 46 virtual void* cast(cid a_class) const { 47 if(void* p = cmp_cast<leaf>(this,a_class)) {return p;} 48 return 0; 49 } 50 virtual cid id_cls() const {return id_class();} 51 public: 52 virtual const std::string& s_def() const = 0; 53 virtual void s_value(std::string&) const = 0; 54 public: 55 leaf(){} 56 virtual ~leaf(){} 57 leaf(const leaf& a_from):iobj(a_from){} 58 leaf& operator=(const leaf&){return *this;} 59 }; 60 61 static const std::string& s_aida_type(int) { 62 static const std::string s_v("int"); 63 return s_v; 64 } 65 static const std::string& s_aida_type(float) { 66 static const std::string s_v("float"); 67 return s_v; 68 } 69 static const std::string& s_aida_type(double) { 70 static const std::string s_v("double"); 71 return s_v; 72 } 73 static const std::string& s_aida_type(const std::string&) { 74 static const std::string s_v("string"); 75 return s_v; 76 } 77 78 static const std::string& s_aida_type_ituple() { 79 static const std::string s_v("ITuple"); 80 return s_v; 81 } 82 83 public: 84 template <class T> 85 class column : public leaf { 86 public: 87 static cid id_class() {return 200+_cid(T());} 88 public: //iobj 89 virtual void* cast(cid a_class) const { 90 if(void* p = cmp_cast< column<T> >(this,a_class)) {return p;} 91 return leaf::cast(a_class); 92 } 93 virtual cid id_cls() const {return id_class();} 94 public: 95 virtual const std::string& name() const {return m_name;} 96 virtual const std::string& aida_type() const {return s_aida_type(T());} 97 public: //leaf 98 virtual const std::string& s_def() const {return m_def;} 99 virtual void s_value(std::string& a_s) const {a_s = tos(m_tmp);} 100 public: 101 column(const std::string& a_name,const T& a_def) 102 :m_name(a_name),m_def(tos(a_def)),m_tmp(a_def) 103 {} 104 virtual ~column(){} 105 protected: 106 column(const column& a_from) 107 :leaf(a_from) 108 ,m_name(a_from.m_name) 109 ,m_def(a_from.m_def) 110 ,m_tmp(a_from.m_tmp) 111 {} 112 column& operator=(const column& a_from){ 113 m_name = a_from.m_name; 114 m_def = a_from.m_def; 115 m_tmp = a_from.m_tmp; 116 return *this; 117 } 118 public: 119 bool fill(const T& a_value) {m_tmp = a_value;return true;} 120 protected: 121 std::string m_name; 122 std::string m_def; 123 T m_tmp; 124 }; 125 126 127 class sub_ntuple : public virtual iobj { 128 public: 129 static cid id_class() {return 300;} 130 public: //iobj 131 virtual void* cast(cid a_class) const { 132 if(void* p = cmp_cast<sub_ntuple>(this,a_class)) {return p;} 133 return 0; 134 } 135 virtual cid id_cls() const {return id_class();} 136 public: 137 virtual const std::string& name() const {return m_name;} 138 virtual const std::string& aida_type() const {return s_aida_type_ituple();} 139 public: 140 sub_ntuple(const std::string& a_name,const std::string& a_spaces) 141 :m_name(a_name),m_spaces(a_spaces){} 142 virtual ~sub_ntuple(){} 143 protected: 144 sub_ntuple(const sub_ntuple& a_from) 145 :iobj(a_from),m_name(a_from.m_name){} 146 sub_ntuple& operator=(const sub_ntuple&){return *this;} 147 public: 148 template <class T> 149 column<T>* create_column(const std::string& a_name,const T& a_def = T()) { 150 if(find_named<iobj>(m_cols,a_name)) return 0; 151 column<T>* col = new column<T>(a_name,a_def); 152 if(!col) return 0; 153 m_cols.push_back(col); 154 return col; 155 } 156 157 sub_ntuple* create_sub_ntuple(const std::string& a_name){ 158 if(find_named<iobj>(m_cols,a_name)) return 0; 159 std::string spaces; 160 for(unsigned int i=0;i<4;i++) spaces += " "; 161 sub_ntuple* col = new sub_ntuple(a_name,m_spaces+spaces); 162 if(!col) return 0; 163 m_cols.push_back(col); 164 return col; 165 } 166 167 168 const std::vector<iobj*>& columns() const {return m_cols;} 169 170 std::string booking(bool a_xml_esc) const { 171 std::string _s; 172 get_booking(m_cols,a_xml_esc,_s); 173 return _s; 174 } 175 void reset() {m_tmp.clear();} 176 const std::string& value() const {return m_tmp;} 177 178 bool add_row() { 179 if(m_cols.empty()) return false; 180 std::ostringstream sout; 181 sout << m_spaces << "<row>" << std::endl; 182 tools_vforcit(iobj*,m_cols,it) { 183 if(sub_ntuple* sub = id_cast<iobj,sub_ntuple>(*(*it))) { 184 sout << m_spaces << " <entryITuple>" << std::endl; 185 sout << sub->value(); 186 sout << m_spaces << " </entryITuple>" << std::endl; 187 sub->reset(); 188 } else if(leaf* lf = id_cast<iobj,leaf>(*(*it))){ 189 std::string _sv; 190 lf->s_value(_sv); 191 sout << m_spaces << " <entry" 192 << " value=\"" << _sv 193 << "\"/>" << std::endl; 194 } 195 } 196 sout << m_spaces << "</row>" << std::endl; 197 198 m_tmp += sout.str(); 199 200 return true; 201 } 202 protected: 203 std::string m_name; 204 std::string m_spaces; 205 std::vector<iobj*> m_cols; 206 std::string m_tmp; 207 }; 208 209 template <class T> 210 class std_vector_column : public leaf { 211 public: 212 static cid id_class() {return 200+_cid_std_vector<T>();} 213 public: //iobj 214 virtual void* cast(cid a_class) const { 215 if(void* p = cmp_cast<std_vector_column>(this,a_class)) {return p;} 216 return leaf::cast(a_class); 217 } 218 virtual cid id_cls() const {return id_class();} 219 public: 220 virtual const std::string& name() const {return m_name;} 221 virtual const std::string& aida_type() const {return s_aida_type(T());} 222 public: //leaf 223 virtual const std::string& s_def() const {return m_def;} //not used. 224 virtual void s_value(std::string& a_s) const { 225 std::ostringstream sout; 226 sout << m_spaces << "<entryITuple>" << std::endl; 227 typedef typename std::vector<T>::const_iterator it_t; 228 for(it_t it=m_user_vec.begin();it!=m_user_vec.end();++it) { 229 sout << m_spaces << " <row><entry" << " value=\"" << tos(*it) << "\"/></row>" << std::endl; 230 } 231 sout << m_spaces << "</entryITuple>" << std::endl; 232 a_s = sout.str(); 233 } 234 public: 235 std_vector_column(const std::string& a_name,std::vector<T>& a_user_vec,const std::string& a_spaces) 236 :m_name(a_name) 237 ,m_user_vec(a_user_vec) 238 ,m_spaces(a_spaces) 239 {} 240 virtual ~std_vector_column(){} 241 protected: 242 std_vector_column(const std_vector_column& a_from) 243 :leaf(a_from) 244 ,m_name(a_from.m_name) 245 ,m_user_vec(a_from.m_user_vec) 246 ,m_spaces(a_from.m_spaces) 247 {} 248 std_vector_column& operator=(const std_vector_column& a_from){ 249 m_name = a_from.m_name; 250 m_spaces = a_from.m_spaces; 251 return *this; 252 } 253 protected: 254 std::string m_name; 255 std::string m_def; //not used; 256 std::vector<T>& m_user_vec; 257 std::string m_spaces; 258 }; 259 260 static leaf* is_std_vector_column(iobj& a_obj) { 261 //200+20+id(basic type) ? 262 int _id = (int)a_obj.id_cls()-220; 263 if((_id<=0)||(_id>=20)) return 0; 264 return id_cast<iobj,leaf>(a_obj); 265 } 266 267 public: 268 ntuple(std::ostream& a_writer,unsigned int a_spaces = 0) 269 :m_writer(a_writer){ 270 for(unsigned int i=0;i<a_spaces;i++) m_spaces += " "; 271 } 272 ntuple(std::ostream& a_writer, 273 std::ostream& a_out, 274 const ntuple_booking& a_bkg, 275 unsigned int a_spaces = 0) 276 :m_writer(a_writer){ 277 for(unsigned int i=0;i<a_spaces;i++) m_spaces += " "; 278 279 const std::vector<column_booking>& cols = a_bkg.columns(); 280 tools_vforcit(column_booking,cols,it){ 281 282 if((*it).cls_id()==_cid(int(0))) { 283 create_column<int>((*it).name()); 284 } else if((*it).cls_id()==_cid(float(0))) { 285 create_column<float>((*it).name()); 286 } else if((*it).cls_id()==_cid(double(0))) { 287 create_column<double>((*it).name()); 288 } else if((*it).cls_id()==_cid(std::string())) { 289 create_column<std::string>((*it).name()); 290 291 } else if((*it).cls_id()==_cid_std_vector<int>()) { 292 std::vector<int>* vec = (std::vector<int>*)(*it).user_obj(); 293 if(vec) { 294 create_column<int>((*it).name(),*vec); 295 } else { 296 a_out << "tools::waxml::ntuple :" 297 << " for std::vector column " << sout((*it).name()) 298 << ", the user vector pointer is null." 299 << std::endl; 300 safe_clear<iobj>(m_cols); 301 return; 302 } 303 } else if((*it).cls_id()==_cid_std_vector<float>()) { 304 std::vector<float>* vec = (std::vector<float>*)(*it).user_obj(); 305 if(vec) { 306 create_column<float>((*it).name(),*vec); 307 } else { 308 a_out << "tools::waxml::ntuple :" 309 << " for std::vector column " << sout((*it).name()) 310 << ", the user vector pointer is null." 311 << std::endl; 312 safe_clear<iobj>(m_cols); 313 return; 314 } 315 } else if((*it).cls_id()==_cid_std_vector<double>()) { 316 std::vector<double>* vec = (std::vector<double>*)(*it).user_obj(); 317 if(vec) { 318 create_column<double>((*it).name(),*vec); 319 } else { 320 a_out << "tools::waxml::ntuple :" 321 << " for std::vector column " << sout((*it).name()) 322 << ", the user vector pointer is null." 323 << std::endl; 324 safe_clear<iobj>(m_cols); 325 return; 326 } 327 328 } else if((*it).cls_id()==_cid_std_vector<std::string>()) { 329 std::vector<std::string>* vec = (std::vector<std::string>*)(*it).user_obj(); 330 if(vec) { 331 create_column<std::string>((*it).name(),*vec); 332 } else { 333 a_out << "tools::waxml::ntuple :" 334 << " for std::vector column " << sout((*it).name()) 335 << ", the user vector pointer is null." 336 << std::endl; 337 safe_clear<iobj>(m_cols); 338 return; 339 } 340 341 } else { 342 a_out << "tools::waxml::ntuple :" 343 << " for column " << sout((*it).name()) 344 << ", type with cid " << (*it).cls_id() << " not yet handled." 345 << std::endl; 346 //throw 347 safe_clear<iobj>(m_cols); 348 return; 349 } 350 } 351 } 352 virtual ~ntuple() { 353 safe_clear<iobj>(m_cols); 354 } 355 protected: 356 ntuple(const ntuple& a_from) 357 :m_writer(a_from.m_writer) 358 ,m_spaces(a_from.m_spaces) 359 {} 360 ntuple& operator=(const ntuple& a_from){ 361 m_spaces = a_from.m_spaces; 362 return *this; 363 } 364 public: 365 const std::vector<iobj*>& columns() const {return m_cols;} 366 367 template <class T> 368 column<T>* create_column(const std::string& a_name,const T& a_def = T()) { 369 if(find_named<iobj>(m_cols,a_name)) return 0; 370 column<T>* col = new column<T>(a_name,a_def); 371 if(!col) return 0; 372 m_cols.push_back(col); 373 return col; 374 } 375 376 template <class T> 377 std_vector_column<T>* create_column(const std::string& a_name,std::vector<T>& a_user_vec) { 378 if(find_named<iobj>(m_cols,a_name)) return 0; 379 std::string spaces; 380 for(unsigned int i=0;i<8;i++) spaces += " "; 381 std_vector_column<T>* col = new std_vector_column<T>(a_name,a_user_vec,m_spaces+spaces); 382 if(!col) return 0; 383 m_cols.push_back(col); 384 return col; 385 } 386 387 template <class T> 388 column<T>* find_column(const std::string& a_name) { 389 iobj* col = find_named<iobj>(m_cols,a_name); 390 if(!col) return 0; 391 return id_cast<iobj, column<T> >(*col); 392 } 393 394 sub_ntuple* create_sub_ntuple(const std::string& a_name){ 395 if(find_named<iobj>(m_cols,a_name)) return 0; 396 std::string spaces; 397 for(unsigned int i=0;i<10;i++) spaces += " "; 398 sub_ntuple* col = new sub_ntuple(a_name,m_spaces+spaces); 399 if(!col) return 0; 400 m_cols.push_back(col); 401 return col; 402 } 403 404 void write_header(const std::string& a_path,const std::string& a_name,const std::string& a_title){ 405 406 // <tuple> : 407 m_writer << m_spaces << " <tuple" 408 << " path=" << sout(to_xml(a_path)) 409 << " name=" << sout(to_xml(a_name)) 410 << " title=" << sout(to_xml(a_title)) 411 << ">" << std::endl; 412 413 // <columns> : 414 m_writer << m_spaces << " <columns>" << std::endl; 415 416 tools_vforcit(iobj*,m_cols,it) { 417 if(leaf* vlf = is_std_vector_column(*(*it))) { 418 m_writer << m_spaces << " <column" 419 << " name=" << sout(to_xml((*it)->name())) 420 << " type=" << sout("ITuple") 421 << " booking=\"{" << vlf->aida_type() << " " << to_xml((*it)->name()) 422 << "}\"" 423 << "/>" << std::endl; 424 } else if(sub_ntuple* sub = id_cast<iobj,sub_ntuple>(*(*it))){ 425 m_writer << m_spaces << " <column" 426 << " name=" << sout(to_xml((*it)->name())) 427 << " type=" << sout("ITuple") 428 << " booking=" << sout(sub->booking(true)) 429 << "/>" << std::endl; 430 } else if(/*leaf* lf =*/ id_cast<iobj,leaf>(*(*it))){ 431 m_writer << m_spaces << " <column" 432 << " name=" << sout(to_xml((*it)->name())) 433 << " type=" << sout((*it)->aida_type()) 434 //<< " default=" << sout(lf->s_def()) //not understood by jas3 435 << "/>" << std::endl; 436 } 437 } 438 439 m_writer << m_spaces << " </columns>" << std::endl; 440 441 // rows : 442 m_writer << m_spaces << " <rows>" << std::endl; 443 } 444 445 bool add_row() { 446 if(m_cols.empty()) return false; 447 m_writer << m_spaces << " <row>" << std::endl; 448 tools_vforcit(iobj*,m_cols,it) { 449 if(leaf* vlf = is_std_vector_column(*(*it))) { 450 std::string _sv; 451 vlf->s_value(_sv); 452 m_writer << _sv; 453 } else if(sub_ntuple* sub = id_cast<iobj,sub_ntuple>(*(*it))){ 454 m_writer << m_spaces << " <entryITuple>" << std::endl; 455 m_writer << sub->value(); 456 m_writer << m_spaces << " </entryITuple>" << std::endl; 457 sub->reset(); 458 } else if(leaf* lf = id_cast<iobj,leaf>(*(*it))){ 459 std::string _sv; 460 lf->s_value(_sv); 461 m_writer << m_spaces << " <entry" 462 << " value=" << sout(_sv) 463 << "/>" << std::endl; 464 } 465 } 466 m_writer << m_spaces << " </row>" << std::endl; 467 return true; 468 } 469 470 void write_trailer() { 471 m_writer << m_spaces << " </rows>" << std::endl; 472 m_writer << m_spaces << " </tuple>" << std::endl; 473 } 474 475 std::string booking(bool a_xml_esc) const { 476 std::string _s; 477 get_booking(m_cols,a_xml_esc,_s); 478 return _s; 479 } 480 481 protected: 482 static void get_booking(const std::vector<iobj*>& a_cols,bool a_xml_esc, 483 std::string& a_string) { 484 a_string += "{"; //we need the + because of the tuple in tuple. 485 486 tools_vforcit(iobj*,a_cols,it) { 487 if(it!=a_cols.begin()) a_string += ","; 488 489 std::string sname = (*it)->name(); 490 if(a_xml_esc) sname = to_xml(sname); 491 492 if(leaf* vlf = is_std_vector_column(*(*it))) { 493 a_string += "ITuple " + (*it)->name() + " = {" + vlf->aida_type() + " " + sname + "}"; 494 495 } else if(sub_ntuple* sub = id_cast<iobj,sub_ntuple>(*(*it))){ 496 a_string += (*it)->aida_type() + " " + sname + " = "; 497 498 get_booking(sub->columns(),a_xml_esc,a_string); 499 } else if(leaf* lf = id_cast<iobj,leaf>(*(*it))){ 500 a_string += (*it)->aida_type() + " " + sname + " = " + lf->s_def(); 501 } 502 } 503 a_string += "}"; 504 } 505 506 protected: 507 std::ostream& m_writer; 508 //std::string m_path; 509 //std::string m_name; 510 //std::string m_title; 511 std::string m_spaces; 512 std::vector<iobj*> m_cols; 513 }; 514 515 }} 516 517 #endif