Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_columns 5 #define tools_columns 6 7 #include "vmanip" 8 9 #include "forit" 10 #include "sout" 11 #include "schar" 12 13 #ifdef TOOLS_MEM 14 #include "mem" 15 #include "S_STRING" 16 #endif 17 18 namespace tools { 19 namespace columns { 20 21 class tree { 22 #ifdef TOOLS_MEM 23 TOOLS_SCLASS(tools::columns::tree) 24 #endif 25 public: 26 tree(tree* a_parent,const std::string& a_dcl):m_parent(a_parent),m_dcl(a_dcl){ 27 #ifdef TOOLS_MEM 28 mem::increment(s_class().c_str()); 29 #endif 30 if(a_parent) a_parent->m_sub.push_back(this); 31 } 32 virtual ~tree(){ 33 clear(); 34 #ifdef TOOLS_MEM 35 mem::decrement(s_class().c_str()); 36 #endif 37 } 38 protected: 39 tree(const tree&) {} 40 tree& operator=(const tree&) {return *this;} 41 public: 42 void clear() { 43 m_dcl.clear(); 44 safe_reverse_clear(m_sub); 45 } 46 void dump_tree(std::ostream& a_out,const std::string& a_margin) { 47 if(m_dcl.size()) a_out << a_margin << m_dcl << std::endl; 48 {tools_vforit(tree*,m_sub,it) { 49 (*it)->dump_tree(a_out,a_margin+" "); 50 }} 51 } 52 public: 53 tree* m_parent; 54 std::string m_dcl; 55 std::vector<tree*> m_sub; 56 }; 57 58 }} 59 60 #include "strip" 61 62 namespace tools { 63 namespace columns { 64 65 class parser { 66 public: 67 parser():m_top(0,""){} 68 virtual ~parser(){m_top.clear();} 69 protected: 70 parser(const parser&):m_top(0,"") {} 71 parser& operator=(const parser&){return *this;} 72 public: 73 bool parse(const std::string& a_s){ 74 m_top.clear(); 75 tree* prev = &m_top; 76 {std::string _s; 77 for(std::string::const_iterator it=a_s.begin();;++it) { 78 if(it==a_s.end()) { 79 if(_s.size()) { 80 new tree(prev,_s); 81 _s.clear(); 82 } 83 break; 84 } else { 85 const char& c = *it; 86 if(c==',') { 87 if(_s.size()) { 88 new tree(prev,_s); 89 _s.clear(); 90 } 91 } else if(c=='{') { 92 tree* _tree = new tree(prev,_s); 93 _s.clear(); 94 95 prev = _tree; 96 } else if(c=='}') { 97 if(_s.size()) { 98 new tree(prev,_s); 99 _s.clear(); 100 } 101 prev = prev->m_parent; 102 if(!prev) return false; //should not happen. 103 } else { 104 _s += c; 105 } 106 } 107 }} 108 return true; 109 } 110 111 void dump(std::ostream& a_out) {m_top.dump_tree(a_out,"");} 112 protected: 113 tree m_top; 114 }; 115 116 }} 117 118 #include "words" 119 #include "value" 120 121 namespace tools { 122 namespace columns { 123 124 inline void delete_columns(std::vector<value>& a_vars) { 125 tools_vforit(value,a_vars,it) { 126 if((*it).type()==value::VOID_STAR) { 127 std::vector<value>* vars = 128 (std::vector<value>*)(*it).get_void_star(); 129 delete_columns(*vars); 130 delete vars; 131 } 132 } 133 a_vars.clear(); 134 } 135 136 inline void copy_columns(const std::vector<value>& a_from,std::vector<value>& a_to) { 137 std::vector<value>::const_iterator it; 138 for(it=a_from.begin();it!=a_from.end();++it) { 139 if((*it).type()==value::VOID_STAR) { 140 std::vector<value>* vars = new std::vector<value>(); 141 value v((void*)vars); 142 v.set_label((*it).label()); 143 a_to.push_back(v); 144 std::vector<value>* p = 145 (std::vector<value>*)(*it).get_void_star(); 146 copy_columns(*p,*vars); 147 } else { 148 a_to.push_back(*it); 149 } 150 } 151 } 152 153 inline void dump_columns(std::ostream& a_out,const std::vector<value>& a_vars,const std::string& a_margin = "") { 154 std::vector<value>::const_iterator it; 155 for(it=a_vars.begin();it!=a_vars.end();++it) { 156 if((*it).type()==value::VOID_STAR) { 157 a_out << a_margin 158 << "ITuple : " << (*it).label() << " : begin " 159 << std::endl; 160 std::vector<value>* vars = (std::vector<value>*)(*it).get_void_star(); 161 dump_columns(a_out,*vars,a_margin+" "); 162 //a_out << a_margin 163 // << "ITuple : " << (*it).label() << " : end " 164 // << std::endl; 165 } else { 166 std::string stype; 167 (*it).s_type(stype); 168 std::string sval; 169 (*it).tos(sval); 170 171 a_out << a_margin 172 << stype << " : " 173 << (*it).label() << " : " 174 << sval 175 << std::endl; 176 } 177 } 178 } 179 180 class finder : public columns::parser { 181 typedef columns::parser parent; 182 public: 183 finder(std::ostream& a_out,const std::string& a_script) 184 :m_out(a_out) 185 ,m_script(a_script) 186 //,fSuccess(false) 187 ,m_cur_type(value::NONE) 188 {} 189 virtual ~finder() {clear();} 190 protected: 191 finder(const finder& a_from):parent(a_from),m_out(a_from.m_out){} 192 finder& operator=(const finder&){return *this;} 193 public: 194 //void setScript(const std::string& a_string) { m_script = a_string;} 195 bool find_variables() { 196 clear(); 197 if(m_script.empty()) return false; //keep old version logic. 198 if(!parse(m_script)) return false; 199 //dump(m_out); 200 //analyse m_top : 201 if(!analyse(m_top,m_stack)) {clear();return false;} 202 return true; 203 } 204 205 void result(std::vector<value>& a_vars) const { 206 a_vars.clear(); 207 copy_columns(m_stack,a_vars); 208 } 209 210 void clear() { 211 m_top.clear(); 212 delete_columns(m_stack); 213 m_cur_type = value::NONE; 214 } 215 /* 216 const std::string& script() const { return m_script;} 217 //bool isSuccess() const { return fSuccess;} 218 std::ostream& out() const {return m_out;} 219 */ 220 protected: 221 bool analyse(columns::tree& a_tree,std::vector<value>& a_stack) { 222 if(a_tree.m_dcl.empty()) { //top 223 //std::cout << "debug : dcl empty" << std::endl; 224 tools_vforit(columns::tree*,a_tree.m_sub,it) { 225 if(!analyse(*(*it),a_stack)) return false; 226 } 227 } else { 228 //std::cout << "debug : dcl not empty" << std::endl; 229 if(is_spaces(a_tree.m_dcl)) return true; 230 value* v = analyse_dcl(a_tree.m_dcl); 231 if(!v) return false; 232 //std::cout << "debug : dcl label " << v->label() << std::endl; 233 if(a_tree.m_sub.size()) { 234 if(v->type()!=value::VOID_STAR) { 235 m_out << "tools::columns::finder::analyse :" 236 << " Expect a VOID_STAR." 237 << std::endl; 238 delete v; 239 return false; 240 } 241 m_cur_type = value::NONE; 242 std::vector<value>* stk = new std::vector<value>(); 243 tools_vforit(columns::tree*,a_tree.m_sub,it) { 244 if(!analyse(*(*it),*stk)) { 245 delete v; 246 return false; 247 } 248 } 249 v->set((void*)stk); 250 } else { 251 m_cur_type = v->type(); 252 } 253 a_stack.push_back(*v); 254 delete v; 255 } 256 return true; 257 } 258 value* analyse_dcl(const std::string& a_s) { 259 std::vector<std::string> ws; 260 words(a_s,"=",false,ws); 261 if(ws.size()==2) { //<type> <name>=<value> 262 std::vector<std::string> swords; 263 words(ws[0]," ",false,swords); 264 if(swords.size()==2) { 265 266 strip(swords[0]); 267 strip(swords[1]); 268 269 if(swords[0]=="ITuple") { 270 271 //create a value::VOID_STAR : 272 value* v = new value((void*)0); 273 v->set_label(swords[1]); 274 return v; 275 276 } else { 277 278 value::e_type type; 279 if(!s2type(swords[0],type)){ 280 m_out << "tools::columns::finder::analyse_dcl :" 281 << " s2type failed for " << sout(swords[0]) << "." 282 << std::endl; 283 return 0; 284 } 285 286 strip(ws[1]); 287 value* v = new_value(type,ws[1]); 288 if(!v) { 289 m_out << "tools::columns::finder::analyse_dcl :" 290 << " syntax error in " << sout(a_s) << "." 291 << " new_value() failed." 292 << std::endl; 293 return 0; 294 } 295 v->set_label(swords[1]); 296 return v; 297 298 } 299 300 } else if(swords.size()==1) { 301 if(m_cur_type==value::NONE) { 302 m_out << "tools::columns::finder::analyse_dcl :" 303 << " (1) current type is NONE." 304 << std::endl; 305 return 0; 306 } 307 308 strip(ws[1]); 309 value* v = new_value(m_cur_type,ws[1]); 310 if(!v) { 311 m_out << "tools::columns::finder::analyse_dcl :" 312 << " syntax error in " << sout(a_s) << "." 313 << " Bad value " << sout(ws[1]) << "." 314 << std::endl; 315 return 0; 316 } 317 v->set_label(swords[0]); 318 return v; 319 320 } else { 321 m_out << "tools::columns::finder::analyse_dcl :" 322 << " syntax error in " << sout(a_s) 323 << ". Case 1." 324 << std::endl; 325 return 0; 326 } 327 328 } else if(ws.size()==1) { 329 //<type> <name> 330 //<type> <name>={ 331 std::vector<std::string> swords; 332 words(ws[0]," ",false,swords); 333 if(swords.size()==2) { 334 strip(swords[0]); 335 strip(swords[1]); 336 337 if(swords[0]=="ITuple") { 338 339 //create a value::VOID_STAR : 340 value* v = new value((void*)0); 341 v->set_label(swords[1]); 342 return v; 343 344 } else { 345 value::e_type type; 346 if(!s2type(swords[0],type)){ 347 m_out << "tools::columns::finder::analyse_dcl :" 348 << " s2type failed for " << sout(swords[0]) << "." 349 << std::endl; 350 return 0; 351 } 352 353 value* v = new_value(type,""); 354 if(!v) { 355 m_out << "tools::columns::finder::analyse_dcl :" 356 << " (2) syntax error in " << sout(ws[0]) << "." 357 << " Unknown type " << sout(swords[0]) << "." 358 << std::endl; 359 return 0; 360 } 361 v->set_label(swords[1]); 362 return v; 363 } 364 365 } else if(swords.size()==1) { 366 367 if(m_cur_type==value::NONE) { 368 m_out << "tools::columns::finder::analyse_dcl :" 369 << " (1) current type is NONE." 370 << std::endl; 371 return 0; 372 } 373 374 value* v = new value(); 375 v->set_type(m_cur_type); 376 v->set_label(swords[0]); 377 return v; 378 379 } else { 380 m_out << "tools::columns::finder::analyse_dcl :" 381 << " syntax error in " << sout(a_s) 382 << ". Case 2." 383 << std::endl; 384 return 0; 385 } 386 387 } else { 388 m_out << "tools::columns::finder::analyse_dcl :" 389 << " syntax error in " << sout(a_s) 390 << ". Case 3." 391 << std::endl; 392 return 0; 393 } 394 } 395 protected: 396 static bool s2type(const std::string& a_s,value::e_type& a_type){ 397 if(a_s=="float") { 398 a_type = value::FLOAT; 399 } else if(a_s=="double") { 400 a_type = value::DOUBLE; 401 //} else if(a_s=="char") { 402 // a_type = value::CHAR; 403 } else if(a_s=="short") { 404 a_type = value::SHORT; 405 } else if(a_s=="int") { 406 a_type = value::INT; 407 } else if(a_s=="long") { 408 a_type = value::INT64; 409 } else if((a_s=="bool")||(a_s=="boolean")) { 410 a_type = value::BOOL; 411 } else if((a_s=="string")||(a_s=="java.lang.String")){ 412 a_type = value::STRING; 413 //} else if(a_s=="byte") { 414 // a_type = value::UNSIGNED_CHAR; 415 416 } else if(a_s=="float[]") { 417 a_type = value::ARRAY_FLOAT; 418 } else if(a_s=="double[]") { 419 a_type = value::ARRAY_DOUBLE; 420 //} else if(a_s=="char[]") { 421 // a_type = value::ARRAY_CHAR; 422 //} else if(a_s=="byte[]") { 423 // a_type = value::ARRAY_UNSIGNED_CHAR; 424 } else if(a_s=="short[]") { 425 a_type = value::ARRAY_SHORT; 426 } else if(a_s=="int[]") { 427 a_type = value::ARRAY_INT; 428 } else if(a_s=="long[]") { 429 a_type = value::ARRAY_INT64; 430 } else if((a_s=="bool[]")||(a_s=="boolean[]")) { 431 a_type = value::ARRAY_BOOL; 432 } else if((a_s=="string[]")||(a_s=="java.lang.String[]")){ 433 a_type = value::ARRAY_STRING; 434 435 // not AIDA : 436 //} else if(a_s=="uchar") { 437 // a_type = value::UNSIGNED_CHAR; 438 } else if(a_s=="ushort") { 439 a_type = value::UNSIGNED_SHORT; 440 } else if(a_s=="uint") { 441 a_type = value::UNSIGNED_INT; 442 } else if(a_s=="ulong") { 443 a_type = value::UNSIGNED_INT64; 444 } else { 445 return false; 446 } 447 return true; 448 } 449 static value* new_value(value::e_type a_type,const std::string& a_v) { 450 if(a_type==value::FLOAT) { 451 float v = 0; 452 if(a_v.size()) {if(!to<float>(a_v,v)) return 0;} 453 return new value(v); 454 } else if(a_type==value::DOUBLE) { 455 double v = 0; 456 if(a_v.size()) {if(!to<double>(a_v,v)) return 0;} 457 return new value(v); 458 //} else if(a_type==value::CHAR) { 459 // char v = 0; 460 // if(a_v.size()) {if(!to<char>(a_v,v)) return 0;} 461 // return new value(v); 462 } else if(a_type==value::SHORT) { 463 short v = 0; 464 if(a_v.size()) {if(!to<short>(a_v,v)) return 0;} 465 return new value(v); 466 } else if(a_type==value::INT) { 467 int v = 0; 468 if(a_v.size()) {if(!to<int>(a_v,v)) return 0;} 469 return new value(v); 470 471 } else if(a_type==value::INT64) { 472 int64 v = 0; 473 if(a_v.size()) {if(!to<int64>(a_v,v)) return 0;} 474 return new value(v); 475 } else if(a_type==value::BOOL) { 476 bool v = false; 477 if(a_v.size()) {if(!to(a_v,v)) return 0;} 478 return new value(v); 479 480 } else if(a_type==value::STRING) { 481 if( (a_v.size()>=2) && (a_v[0]=='"') && (a_v[a_v.size()-1]=='"') ){ 482 return new value(a_v.substr(1,a_v.size()-2)); 483 } else { 484 return new value(a_v); 485 } 486 487 //} else if(a_type==value::UNSIGNED_CHAR) { 488 // unsigned short v = 0; 489 // if(a_v.size()) {if(!to<unsigned short>(a_v,v)) return 0;} 490 // return new value((unsigned char)v); 491 492 } else if(a_type==value::UNSIGNED_SHORT) { 493 unsigned short v = 0; 494 if(a_v.size()) {if(!to<unsigned short>(a_v,v)) return 0;} 495 return new value(v); 496 } else if(a_type==value::UNSIGNED_INT) { 497 unsigned int v = 0; 498 if(a_v.size()) {if(!to<unsigned int>(a_v,v)) return 0;} 499 return new value(v); 500 501 } else if(a_type==value::UNSIGNED_INT64) { 502 uint64 v = 0; 503 if(a_v.size()) {if(!to<uint64>(a_v,v)) return 0;} 504 return new value(v); 505 506 } else if(a_type==value::ARRAY_FLOAT) { 507 if(a_v.size()) return 0; 508 value* v = new value(); 509 v->set_type(value::ARRAY_FLOAT); 510 return v; 511 } else if(a_type==value::ARRAY_DOUBLE) { 512 if(a_v.size()) return 0; 513 value* v = new value(); 514 v->set_type(value::ARRAY_DOUBLE); 515 return v; 516 //} else if(a_type==value::ARRAY_UNSIGNED_CHAR) { 517 // if(a_v.size()) return 0; 518 // value* v = new value(); 519 // v->set_type(value::ARRAY_UNSIGNED_CHAR); 520 // return v; 521 //} else if(a_type==value::ARRAY_CHAR) { 522 // if(a_v.size()) return 0; 523 // value* v = new value(); 524 // v->set_type(value::ARRAY_CHAR); 525 // return v; 526 } else if(a_type==value::ARRAY_SHORT) { 527 if(a_v.size()) return 0; 528 value* v = new value(); 529 v->set_type(value::ARRAY_SHORT); 530 return v; 531 } else if(a_type==value::ARRAY_INT) { 532 if(a_v.size()) return 0; 533 value* v = new value(); 534 v->set_type(value::ARRAY_INT); 535 return v; 536 } else if(a_type==value::ARRAY_INT64) { 537 if(a_v.size()) return 0; 538 value* v = new value(); 539 v->set_type(value::ARRAY_INT64); 540 return v; 541 } else if(a_type==value::ARRAY_BOOL) { 542 if(a_v.size()) return 0; 543 value* v = new value(); 544 v->set_type(value::ARRAY_BOOL); 545 return v; 546 } else if(a_type==value::ARRAY_STRING) { 547 if(a_v.size()) return 0; 548 value* v = new value(); 549 v->set_type(value::ARRAY_STRING); 550 return v; 551 } else { 552 return 0; 553 } 554 } 555 public: 556 std::ostream& m_out; 557 std::string m_script; 558 std::vector<value> m_stack; 559 value::e_type m_cur_type; 560 //bool fSuccess; 561 }; 562 563 }} 564 565 #endif