1 /**************************************************************************/ 2 /* File: flags.cpp */ 3 /* Author: Joachim Schoeberl */ 4 /* Date: 10. Oct. 96 */ 5 /**************************************************************************/ 6 7 #include "flags.hpp" 8 9 #ifdef WIN32 10 #include <float.h> 11 #endif 12 13 #include <algorithm> 14 15 namespace ngcore 16 { 17 using std::string; 18 using std::endl; Flags()19 Flags :: Flags () { ; } 20 Flags(const Flags & flags)21 Flags :: Flags (const Flags & flags) 22 { 23 string name; 24 for (int i = 0; i < flags.GetNStringFlags(); i++) 25 { 26 string str = flags.GetStringFlag (i, name); 27 SetFlag (name, str); 28 } 29 for (int i = 0; i < flags.GetNNumFlags(); i++) 30 { 31 double val = flags.GetNumFlag (i, name); 32 SetFlag (name, val); 33 } 34 for (int i = 0; i < flags.GetNDefineFlags(); i++) 35 { 36 bool val = flags.GetDefineFlag (i, name); 37 SetFlag (name, val); 38 } 39 for (int i = 0; i < flags.GetNNumListFlags(); i++) 40 { 41 auto numa = flags.GetNumListFlag (i, name); 42 SetFlag (name, *numa); 43 } 44 for (int i = 0; i < flags.GetNStringListFlags(); i++) 45 { 46 auto stra = flags.GetStringListFlag (i, name); 47 SetFlag (name, *stra); 48 } 49 for (int i = 0; i < flags.GetNFlagsFlags(); i++) 50 { 51 auto lflags = flags.GetFlagsFlag (i, name); 52 SetFlag (name, lflags); 53 } 54 for(auto i : Range(flags.anyflags.Size())) 55 { 56 SetFlag(flags.anyflags.GetName(i), flags.anyflags[i]); 57 } 58 } 59 Flags(Flags && flags)60 Flags :: Flags (Flags && flags) 61 : strflags(flags.strflags), numflags(flags.numflags), 62 defflags(flags.defflags), strlistflags(flags.strlistflags), 63 numlistflags(flags.numlistflags) { ; } 64 Flags(std::initializer_list<string> list)65 Flags :: Flags (std::initializer_list<string> list) 66 { 67 for (auto i = list.begin(); i < list.end(); i++) 68 SetCommandLineFlag ((string("-")+*i).c_str()); 69 } 70 71 Flags(string f1,string f2,string f3,string f4,string f5)72 Flags :: Flags (string f1, string f2, string f3, string f4, string f5) 73 { 74 SetCommandLineFlag ((string("-")+f1).c_str()); 75 if (f2.length()) SetCommandLineFlag ( (string("-")+f2).c_str() ); 76 if (f3.length()) SetCommandLineFlag ( (string("-")+f3).c_str() ); 77 if (f4.length()) SetCommandLineFlag ( (string("-")+f4).c_str() ); 78 if (f5.length()) SetCommandLineFlag ( (string("-")+f5).c_str() ); 79 } 80 ~Flags()81 Flags :: ~Flags () 82 { 83 DeleteFlags (); 84 } 85 DeleteFlags()86 void Flags :: DeleteFlags () 87 { 88 strflags.DeleteAll(); 89 numflags.DeleteAll(); 90 defflags.DeleteAll(); 91 strlistflags.DeleteAll(); 92 numlistflags.DeleteAll(); 93 } 94 95 SetFlag(const char * name,bool b)96 Flags Flags :: SetFlag (const char * name, bool b) && 97 { 98 this -> SetFlag (name, b); 99 return std::move(*this); 100 } 101 SetFlag(const char * name,double val)102 Flags Flags :: SetFlag (const char * name, double val) && 103 { 104 this -> SetFlag (name, val); 105 return std::move(*this); 106 } 107 108 109 SetFlag(const char * name,const string & val)110 Flags & Flags :: SetFlag (const char * name, const string & val) 111 { 112 strflags.Set (name, val); 113 return *this; 114 } 115 SetFlag(const char * name,double val)116 Flags & Flags :: SetFlag (const char * name, double val) & 117 { 118 numflags.Set (name, val); 119 return *this; 120 } 121 SetFlag(const char * name,bool b)122 Flags & Flags :: SetFlag (const char * name, bool b) & 123 { 124 defflags.Set (name, b); 125 return *this; 126 } 127 SetFlag(const char * name,Flags & val)128 Flags & Flags :: SetFlag (const char * name, Flags & val) & 129 { 130 flaglistflags.Set (name, val); 131 return *this; 132 } 133 134 135 SetFlag(const string & name,const string & val)136 Flags & Flags :: SetFlag (const string & name, const string & val) 137 { 138 // char * hval = new char[strlen (val) + 1]; 139 // strcpy (hval, val); 140 strflags.Set (name, val); 141 return *this; 142 } 143 SetFlag(const string & name,double val)144 Flags & Flags :: SetFlag (const string & name, double val) 145 { 146 numflags.Set (name, val); 147 return *this; 148 } 149 SetFlag(const string & name,bool b)150 Flags & Flags :: SetFlag (const string & name, bool b) 151 { 152 defflags.Set (name, b); 153 return *this; 154 } 155 SetFlag(const string & name,Flags & val)156 Flags & Flags :: SetFlag (const string & name, Flags & val) 157 { 158 flaglistflags.Set (name, val); 159 return *this; 160 } 161 SetFlag(const string & name,const Array<string> & val)162 Flags & Flags :: SetFlag (const string & name, const Array<string> & val) 163 { 164 auto strarray = std::make_shared<Array<string>>(val); 165 /* 166 for (int i = 0; i < val.Size(); i++) 167 { 168 strarray->Append (new char[strlen(val[i])+1]); 169 strcpy (strarray->Last(), val[i]); 170 } 171 */ 172 strlistflags.Set (name, strarray); 173 return *this; 174 } 175 SetFlag(const string & name,const Array<double> & val)176 Flags & Flags :: SetFlag (const string & name, const Array<double> & val) 177 { 178 // Array<double> * numarray = new Array<double>(val); 179 auto numarray = std::make_shared<Array<double>> (val); 180 181 numlistflags.Set (name, numarray); 182 return *this; 183 } 184 SetFlag(const string & name,const std::any & val)185 Flags & Flags :: SetFlag (const string & name, const std::any & val) 186 { 187 anyflags.Set(name, val); 188 return *this; 189 } 190 GetStringFlag(const string & name,const char * def) const191 string Flags :: GetStringFlag (const string & name, const char * def) const 192 { 193 if (strflags.Used (name)) 194 return strflags[name]; 195 else 196 { 197 if (!def) return string(""); 198 return def; 199 } 200 } 201 GetStringFlag(const string & name,string def) const202 string Flags :: GetStringFlag (const string & name, string def) const 203 { 204 if (strflags.Used (name)) 205 return strflags[name]; 206 else 207 return def; 208 } 209 210 GetNumFlag(const string & name,double def) const211 double Flags :: GetNumFlag (const string & name, double def) const 212 { 213 if (numflags.Used (name)) 214 return numflags[name]; 215 else 216 return def; 217 } 218 GetNumFlagPtr(const string & name) const219 const double * Flags :: GetNumFlagPtr (const string & name) const 220 { 221 if (numflags.Used (name)) 222 return & ((SymbolTable<double>&)numflags)[name]; 223 else 224 return NULL; 225 } 226 GetNumFlagPtr(const string & name)227 double * Flags :: GetNumFlagPtr (const string & name) 228 { 229 if (numflags.Used (name)) 230 return & ((SymbolTable<double>&)numflags)[name]; 231 else 232 return NULL; 233 } 234 235 /* 236 int Flags :: GetDefineFlag (const char * name) const 237 { 238 return defflags.Used (name); 239 } 240 */ GetDefineFlag(const string & name) const241 bool Flags :: GetDefineFlag (const string & name) const throw() 242 { 243 if (!defflags.Used (name)) return false; 244 return defflags[name]; 245 } 246 GetDefineFlagX(const string & name) const247 xbool Flags :: GetDefineFlagX (const string & name) const throw() 248 { 249 if (!defflags.Used (name)) return maybe; 250 return bool(defflags[name]); 251 } 252 253 254 const Array<string> & GetStringListFlag(const string & name) const255 Flags :: GetStringListFlag (const string & name) const 256 { 257 if (strlistflags.Used (name)) 258 return *strlistflags[name]; 259 else 260 { 261 static Array<string> hstra(0); 262 return hstra; 263 } 264 } 265 266 const Array<double> & GetNumListFlag(const string & name) const267 Flags ::GetNumListFlag (const string & name) const 268 { 269 if (numlistflags.Used (name)) 270 return *numlistflags[name]; 271 else 272 { 273 static Array<double> hnuma(0); 274 return hnuma; 275 } 276 } 277 278 const Flags & GetFlagsFlag(const string & name) const279 Flags ::GetFlagsFlag (const string & name) const 280 { 281 if (flaglistflags.Used (name)) 282 return flaglistflags[name]; 283 else 284 { 285 static Flags empty; 286 return empty; 287 } 288 } 289 GetAnyFlag(const std::string & name) const290 const std::any& Flags:: GetAnyFlag(const std::string& name) const 291 { 292 if(anyflags.Used(name)) 293 return anyflags[name]; 294 static std::any empty; 295 return empty; 296 } 297 StringFlagDefined(const string & name) const298 bool Flags :: StringFlagDefined (const string & name) const 299 { 300 return strflags.Used (name); 301 } 302 NumFlagDefined(const string & name) const303 bool Flags :: NumFlagDefined (const string &name) const 304 { 305 return numflags.Used (name); 306 } 307 FlagsFlagDefined(const string & name) const308 bool Flags :: FlagsFlagDefined (const string &name) const 309 { 310 return flaglistflags.Used (name); 311 } 312 StringListFlagDefined(const string & name) const313 bool Flags :: StringListFlagDefined (const string & name) const 314 { 315 return strlistflags.Used (name); 316 } 317 NumListFlagDefined(const string & name) const318 bool Flags :: NumListFlagDefined (const string & name) const 319 { 320 return numlistflags.Used (name); 321 } 322 AnyFlagDefined(const string & name) const323 bool Flags :: AnyFlagDefined (const string& name) const 324 { 325 return anyflags.Used(name); 326 } 327 SaveFlags(ostream & str) const328 void Flags :: SaveFlags (ostream & str) const 329 { 330 for (int i = 0; i < strflags.Size(); i++) 331 str << strflags.GetName(i) << " = " << strflags[i] << endl; 332 for (int i = 0; i < numflags.Size(); i++) 333 str << numflags.GetName(i) << " = " << numflags[i] << endl; 334 for (int i = 0; i < defflags.Size(); i++) 335 str << defflags.GetName(i) << " = " << (defflags[i] ? "_TRUE" : "_FALSE") << endl; 336 for (int i = 0; i < flaglistflags.Size(); i++) 337 str << flaglistflags.GetName(i) << " =*" << flaglistflags[i] << endl; 338 for (int i = 0; i < numlistflags.Size(); i++) 339 { 340 str << numlistflags.GetName(i) << " = ["; 341 int j = 0; 342 for (j = 0; j + 1 < numlistflags[i]->Size(); ++j) 343 str << (*numlistflags[i])[j] << ", "; 344 if (numlistflags[i]->Size()) 345 str << (*numlistflags[i])[j]; 346 str << "]" << endl; 347 } 348 } 349 SaveFlags(const char * filename) const350 void Flags :: SaveFlags (const char * filename) const 351 { 352 std::ofstream outfile (filename); 353 SaveFlags(outfile); 354 } 355 356 357 PrintFlags(ostream & ost) const358 void Flags :: PrintFlags (ostream & ost) const 359 { 360 for (int i = 0; i < strflags.Size(); i++) 361 ost << strflags.GetName(i) << " = " << strflags[i] << endl; 362 for (int i = 0; i < numflags.Size(); i++) 363 ost << numflags.GetName(i) << " = " << numflags[i] << endl; 364 for (int i = 0; i < defflags.Size(); i++) 365 ost << defflags.GetName(i) << endl; 366 for (int i = 0; i < strlistflags.Size(); i++) 367 ost << strlistflags.GetName(i) << " = " << *strlistflags[i] << endl; 368 for (int i = 0; i < numlistflags.Size(); i++) 369 ost << numlistflags.GetName(i) << " = " << *numlistflags[i] << endl; 370 for (int i = 0; i < flaglistflags.Size(); i++) 371 ost << flaglistflags.GetName(i) << " = " << flaglistflags[i] << endl; 372 } 373 LoadFlags(const char * filename,SymbolTable<Flags> * sf)374 void Flags :: LoadFlags (const char * filename, SymbolTable<Flags> * sf) 375 { 376 std::ifstream str(filename); 377 LoadFlags(str,sf); 378 } 379 LoadFlags(std::istream & istr,SymbolTable<Flags> * sf)380 void Flags :: LoadFlags (std::istream & istr, SymbolTable<Flags> * sf ) 381 { 382 char str[100]; 383 char ch; 384 // double val; 385 386 while (istr.good()) 387 { 388 string name; 389 string content; 390 string line; 391 getline(istr, line); 392 std::istringstream line_stream(line); 393 394 getline(line_stream, name, '='); 395 name.erase(std::remove(name.begin(), name.end(), ' '), name.end()); 396 397 getline(line_stream, content); 398 content.erase(std::remove(content.begin(), content.end(), ' '), content.end()); 399 400 // if (name[0] == '/' && name[1] == '/') 401 // { 402 // ch = 0; 403 // while (ch != '\n' && istr.good()) 404 // { 405 // ch = istr.get(); 406 // } 407 // continue; 408 // } 409 410 if (strlen(content.c_str())==0) 411 { 412 SetFlag (name); 413 continue; 414 } 415 else 416 { 417 std::istringstream content_stream(content); 418 419 content_stream >> ch; 420 if (ch != '*') 421 { 422 if (ch == '[') 423 { 424 // content_stream.putback (ch); 425 // content_stream >> ch; 426 string inner_string; 427 getline(content_stream, inner_string, ']'); 428 std::istringstream inner_string_stream(inner_string); 429 430 Array<double> values; 431 Array<string> strings; 432 433 string cur; 434 while (getline(inner_string_stream, cur, ',')) 435 { 436 char* endptr; 437 double vald = strtod (cur.c_str(), &endptr); 438 439 if (endptr != cur.c_str() && strings.Size() == 0) 440 values.Append(vald); 441 else 442 strings.Append(cur); 443 } 444 if (strings.Size() > 0) 445 SetFlag(name, strings); 446 else 447 SetFlag(name, values); 448 } 449 else 450 { 451 if(content == "_TRUE" || content == "_FALSE") 452 { 453 SetFlag(name, (content =="_TRUE") ? true : false); 454 continue; 455 } 456 char* endptr; 457 double vald = strtod (content.c_str(), &endptr); 458 if (endptr != content.c_str()) 459 SetFlag (name, vald); 460 else 461 SetFlag (name, content); 462 } 463 } 464 else 465 { 466 content_stream.clear(); 467 content_stream >> str; 468 if (sf) 469 SetFlag (name, (*sf)[str]); 470 else 471 throw Exception (" no symboltable of flags "); 472 } 473 } 474 } 475 } 476 DoArchive(Archive & archive)477 void Flags :: DoArchive(Archive & archive) 478 { 479 archive & strflags & numflags & defflags & numlistflags & strlistflags & flaglistflags; 480 } 481 Update(const Flags & other)482 void Flags :: Update(const Flags& other) 483 { 484 strflags.Update(other.strflags); 485 numflags.Update(other.numflags); 486 defflags.Update(other.defflags); 487 numlistflags.Update(other.numlistflags); 488 strlistflags.Update(other.strlistflags); 489 flaglistflags.Update(other.flaglistflags); 490 } 491 SetCommandLineFlag(const char * st,SymbolTable<Flags> * sf)492 void Flags :: SetCommandLineFlag (const char * st, SymbolTable<Flags> * sf ) 493 { 494 //cout << "SetCommandLineFlag: flag = " << st << endl; 495 std::istringstream inst( (char *)st); 496 497 char name[100]; 498 double val; 499 500 501 if (st[0] != '-') 502 { 503 std::cerr << "flag must start with '-'" << endl; 504 return; 505 } 506 507 // flag with double -- 508 if (st[1] == '-') st++; 509 510 const char * pos = strchr (st, '='); 511 const char * posstar = strchr (st, '*'); 512 const char * posbrack = strchr (st, '['); 513 514 if (!pos) 515 { 516 // (cout) << "Add def flag: " << st+1 << endl; 517 SetFlag (st+1); 518 } 519 else 520 { 521 //cout << "pos = " << pos << endl; 522 523 strncpy (name, st+1, (pos-st)-1); 524 name[pos-st-1] = 0; 525 526 //cout << "name = " << name << endl; 527 528 pos++; 529 char * endptr = NULL; 530 val = strtod (pos, &endptr); 531 532 /* 533 cout << "val = " << val << endl; 534 cout << "isfinite = " << std::isfinite (val) << endl; 535 cout << "isinf = " << std::isinf (val) << endl; 536 cout << "pos = " << pos << ", endpos = " << endptr << endl; 537 */ 538 if (endptr != pos && !std::isfinite (val)) 539 endptr = const_cast<char *>(pos); 540 541 /* 542 #ifdef WIN32 543 if(endptr != pos && !_finite(val)) 544 endptr = const_cast<char *>(pos); 545 #else 546 #ifdef MACOS 547 if(endptr != pos && (__isnand(val) || __isinfd(val))) 548 endptr = const_cast<char *>(pos); 549 #else 550 #ifdef SUN 551 #else 552 if(endptr != pos && (std::isnan(val) || std::isinf(val))) 553 endptr = const_cast<char *>(pos); 554 #endif 555 #endif 556 #endif 557 */ 558 559 //cout << "val = " << val << endl; 560 561 if (!posbrack) 562 { 563 if (posstar) 564 { 565 pos++; 566 if (sf) 567 SetFlag (name, (*sf)[pos]); 568 else 569 throw Exception (" no symboltable of flags "); 570 } 571 else if (endptr == pos) 572 { 573 // string-flag 574 //(cout) << "Add String Flag: " << name << " = " << pos << endl; 575 SetFlag (name, pos); 576 } 577 else 578 { 579 // num-flag 580 //(cout) << "Add Num Flag: " << name << " = " << val << endl; 581 SetFlag (name, val); 582 } 583 } 584 else 585 { 586 // list-flag 587 char hc; 588 double val; 589 590 val = strtod (posbrack+1, &endptr); 591 if (endptr != posbrack+1) 592 { 593 Array<double> values; 594 595 std::istringstream ist(posbrack); 596 ist >> hc; // '[' 597 ist >> val; 598 while (ist.good()) 599 { 600 values.Append (val); 601 ist >> hc; // ',' 602 ist >> val; 603 } 604 SetFlag (name, values); 605 } 606 else 607 { 608 // to be cleand up ... 609 Array<char *> strs; 610 611 posbrack++; 612 char * hstr = new char[strlen(posbrack)+1]; 613 strcpy (hstr, posbrack); 614 615 char * chp = hstr; 616 617 bool start = 1; 618 while (*chp && *chp != ']') 619 { 620 if (start) 621 strs.Append (chp); 622 start = 0; 623 if (*chp == ',') 624 { 625 *chp = 0; 626 start = 1; 627 } 628 chp++; 629 } 630 *chp = 0; 631 632 Array<string> strings; 633 for (int i = 0; i < strs.Size(); i++) 634 strings.Append (string (strs[i])); 635 SetFlag (name, strings); 636 delete [] hstr; 637 } 638 } 639 } 640 } 641 } // namespace ngcore 642