Config.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. // STL includes
  2. #include <assert.h>
  3. #include <fstream>
  4. // nice-core includes
  5. #include "core/basics/Exception.h"
  6. #include "core/basics/Config.h"
  7. #include "core/basics/ossettings.h"
  8. #include "core/basics/StringTools.h"
  9. #include "core/basics/FileName.h"
  10. using namespace NICE;
  11. using namespace std;
  12. #undef DEBUGCONFIG
  13. #define DEBUGPRINT printf
  14. Config::Config ()
  15. {
  16. ioUntilEndOfFile = true;
  17. }
  18. Config::Config ( const std::string & configfn )
  19. {
  20. if ( configfn.size() >0 ) {
  21. read(configfn);
  22. }
  23. ioUntilEndOfFile = true;
  24. m_sConfigFilename = configfn;
  25. }
  26. Config::Config ( int argc,
  27. char **argv )
  28. {
  29. readFromArguments ( argc, argv );
  30. std::string configfile = gS("main", "config", "" );
  31. std::cerr << "configfile: " << configfile << std::endl;
  32. ioUntilEndOfFile = gB("main", "ioUntilEndOfFile", true );
  33. if ( configfile.size() > 0 )
  34. readWithoutOverwrite ( configfile.c_str(), CONFIG_DO_NOT_OVERWRITE_VALUES /*do not overwrite values*/ );
  35. }
  36. Config::Config ( const Config & conf ) : Persistent()
  37. {
  38. ioUntilEndOfFile = true;
  39. m_sConfigFilename = conf.m_sConfigFilename;
  40. confB.copyFrom ( conf.confB );
  41. confD.copyFrom ( conf.confD );
  42. confI.copyFrom ( conf.confI );
  43. confS.copyFrom ( conf.confS );
  44. }
  45. Config::~Config()
  46. {
  47. }
  48. void Config::clear()
  49. {
  50. #if defined DEBUGCONFIG
  51. DEBUGPRINT( "Config: clear ...\n" );
  52. #endif
  53. confB.clear();
  54. confD.clear();
  55. confI.clear();
  56. confS.clear();
  57. }
  58. void Config::addKeyValuePair ( const std::string & block,
  59. const std::string & key,
  60. const std::string & value )
  61. {
  62. vector<string> submatches;
  63. #if defined DEBUGCONFIG
  64. DEBUGPRINT( "Config: analyzing value %s\n", value.c_str() );
  65. #endif
  66. if ( StringTools::regexMatch ( value, "^ *([-[:digit:]]+) *;?$", submatches ) &&
  67. (submatches.size() == 2) ) {
  68. #if defined DEBUGCONFIG
  69. DEBUGPRINT ( "Config: integer value\n");
  70. #endif
  71. int v;
  72. v = StringTools::convert<int> ( submatches[1] );
  73. confI.store ( block, key, v );
  74. } else if ( value.compare("true") == 0 ) {
  75. #if defined DEBUGCONFIG
  76. DEBUGPRINT( "Config: boolean value\n");
  77. #endif
  78. confB.store ( block, key, true );
  79. } else if ( value.compare("false") == 0 ) {
  80. #if defined DEBUGCONFIG
  81. DEBUGPRINT ( "Config: boolean value\n");
  82. #endif
  83. confB.store ( block, key, false );
  84. } else if ( StringTools::regexMatch ( value, "^ *([-e.[:digit:]]+) *;?$", submatches ) &&
  85. (submatches.size() == 2) )
  86. {
  87. double v;
  88. if ( ! StringTools::convert<double> ( submatches[1], v ) )
  89. {
  90. DEBUGPRINT ( "Config: please ask Erik to debug this part of Config.cpp\n");
  91. exit(-1);
  92. }
  93. #if defined DEBUGCONFIG
  94. DEBUGPRINT ( "Config: double value\n");
  95. #endif
  96. confD.store ( block, key, v );
  97. } else {
  98. #if defined DEBUGCONFIG
  99. DEBUGPRINT ( "Config: string value\n");
  100. #endif
  101. string trimValue = value;
  102. StringTools::trimbounds ( trimValue, '\"' );
  103. StringTools::trimbounds ( trimValue, '\'' );
  104. confS.store ( block, key, trimValue );
  105. }
  106. }
  107. void Config::readFromArguments ( int argc, char **argv )
  108. {
  109. std::string section;
  110. std::string key;
  111. std::string value;
  112. ioUntilEndOfFile = true;
  113. for ( int i = 1 ; i < argc ; i++ )
  114. {
  115. if ( argv[i] == NULL ) break;
  116. std::string arg ( argv[i] );
  117. vector<string> submatches;
  118. bool match = false;
  119. match = StringTools::regexMatch ( arg, "^--?([[:alpha:]][[:alpha:][:digit:]_-]*):([[:alpha:][:digit:]_-]+)", submatches );
  120. if ( (match) && (submatches.size() == 3) ) {
  121. if ( key.size() > 0 ) {
  122. addArgBoolean ( section, key );
  123. }
  124. section = submatches[1];
  125. key = submatches[2];
  126. continue;
  127. }
  128. match = StringTools::regexMatch ( arg, "^--?([[:alpha:]][[:alpha:][:digit:]_-]*)", submatches );
  129. if ( (match) && (submatches.size() == 2) ) {
  130. if ( key.size() > 0 )
  131. {
  132. addArgBoolean ( section, key );
  133. }
  134. section = "main";
  135. key = submatches[1];
  136. continue;
  137. }
  138. value = string(argv[i]);
  139. if ( key.size() <= 0 )
  140. {
  141. // add to more options
  142. moreOptions.push_back ( value );
  143. continue;
  144. }
  145. #if defined DEBUGCONFIG
  146. cout << "Config: add command line option: " << section << ":" << key << " = " << value << endl;
  147. #endif
  148. addKeyValuePair ( section, key, value );
  149. key = "";
  150. }
  151. if ( key.size() > 0 )
  152. addArgBoolean ( section, key );
  153. }
  154. // refactor-nice.pl: check this substitution
  155. // old: void Config::addArgBoolean ( const string & section, const string & key )
  156. void Config::addArgBoolean ( const std::string & section, const std::string & key )
  157. {
  158. vector<string> submatches;
  159. if ( StringTools::regexMatch ( key, "^no-(.*)$", submatches )
  160. && (submatches.size() == 2) )
  161. {
  162. confB.store ( section, submatches[1], false );
  163. } else {
  164. confB.store ( section, key, true );
  165. }
  166. }
  167. void Config::restore (istream & is, int format)
  168. {
  169. std::string block = "main";
  170. std::string key;
  171. std::string value;
  172. std::string line;
  173. int count = 0;
  174. //check for the first word
  175. //if this is "Config::store--PreciseTermination" then we do not read until eof
  176. //but bis the precise termination statement "Config::store--done" arises
  177. std::string firstWord;
  178. if (! is.eof() )
  179. {
  180. is >> firstWord;
  181. if ( firstWord.compare( "Config::store--PreciseTermination" ) == 0)
  182. {
  183. ioUntilEndOfFile = false;
  184. }
  185. else
  186. ioUntilEndOfFile = true;
  187. }
  188. //jump to the beginning of the file
  189. is.clear();
  190. is.seekg(0, ios::beg);
  191. //we keep the while-loop untached, but break out of ioUntilEndOfFile is false and we reached the termination-statement
  192. while (! is.eof())
  193. {
  194. size_t i=0;
  195. if ( !getline(is, line) )
  196. break;
  197. //do we have to check for the precise termination statement and reaches it yet?
  198. if ( (!ioUntilEndOfFile) && (line.compare("Config::store--done") == 0) )
  199. break;
  200. if ( line.size() <= 0 )
  201. continue;
  202. size_t len = line.size();
  203. count++;
  204. if ( (len < 1) || (line[0] == '#' ) )
  205. continue;
  206. line = StringTools::chomp ( line );
  207. len = line.size();
  208. #if defined DEBUGCONFIG
  209. DEBUGPRINT ("Config: (%d) '%s' (len = %d) / %s\n", (int)count, line.c_str(), (int)len,
  210. block.c_str());
  211. #endif
  212. while ( ( (line[i] == '\t') || (line[i]==' ') ) && (i<len)) i++;
  213. if ( i == len ) continue;
  214. if ( line[i] == '[' ) {
  215. size_t j = i+1;
  216. while ((line[j]!=']') && (j<len)) j++;
  217. if ( (j == len) || (i==j-1) ) continue;
  218. block = line.substr( i+1, j-i-1 );
  219. #if defined DEBUGCONFIG
  220. DEBUGPRINT ("Config: reading block %s\n", block.c_str());
  221. #endif
  222. StringTools::normalize_string(block);
  223. continue;
  224. }
  225. if ( line[i] == '%' ) {
  226. size_t j = i+1;
  227. while ((line[j]!='%') && (j<len)) j++;
  228. if ( (j == len) || (i==j-1) ) continue;
  229. std::string includefile = line.substr( i+1, j-i-1 );
  230. #if defined DEBUGCONFIG
  231. DEBUGPRINT ("Config: including config file %s\n", includefile.c_str());
  232. #endif
  233. StringTools::normalize_string ( includefile );
  234. readWithoutOverwrite ( includefile.c_str(), format );
  235. continue;
  236. }
  237. size_t p = i;
  238. while ( (line[p]!='=') && (p<len) ) p++;
  239. if ( (p >= len-1) || (p<=i) ) continue;
  240. key = line.substr( i, p-i );
  241. value = line.substr( p+1 ); // with only one argument, substr copies from the specified position until the end of the string
  242. StringTools::normalize_string(value);
  243. StringTools::normalize_string(key);
  244. // transform(key.begin(), key.end(), key.begin(), ::tolower);
  245. #if defined DEBUGCONFIG
  246. DEBUGPRINT ("Config: found key value pair (%s,%s) in section %s\n",
  247. key.c_str(), value.c_str(), block.c_str());
  248. #endif
  249. if ( (format == CONFIG_OVERWRITE_VALUES) || ( !keyExists(block, key) ) )
  250. addKeyValuePair ( block, key, value );
  251. }
  252. #if defined DEBUGCONFIG
  253. DEBUGPRINT ("Config: successfully loaded.\n" );
  254. DEBUGPRINT ("Config: %d double values\n", (int)confD.size() );
  255. DEBUGPRINT ("Config: %d integer values\n", (int)confI.size() );
  256. DEBUGPRINT ("Config: %d bool values\n", (int)confB.size() );
  257. // refactor-nice.pl: check this substitution
  258. // old: DEBUGPRINT ("Config: %d string values\n", (int)confS.size() );
  259. DEBUGPRINT ("Config: %d std::string values\n", (int)confS.size() );
  260. #endif
  261. }
  262. bool Config::keyExists ( const std::string & block, const std::string & key ) const
  263. {
  264. return ( confS.keyExists ( block, key ) ||
  265. confI.keyExists ( block, key ) ||
  266. confB.keyExists ( block, key ) ||
  267. confD.keyExists ( block, key ) );
  268. }
  269. void Config::addHelp ( const std::string & block, const std::string & key,
  270. const std::string & helpText )
  271. {
  272. helpTexts[ block + "::" + key ] = helpText;
  273. }
  274. std::string Config::help ( const std::string & block, const std::string & key ) const
  275. {
  276. std::string k = block + "::" + key;
  277. map<string, string>::const_iterator i = helpTexts.find(k);
  278. if ( i == helpTexts.end() )
  279. return "no helping information for this variable, sorry!";
  280. else
  281. return i->second;
  282. }
  283. std::string Config::gS(const std::string & key) const
  284. {
  285. return gS(key, "main");
  286. }
  287. std::string Config::gS(const std::string & block, const std::string & key) const
  288. {
  289. std::string v ("");
  290. if ( confS.find(block, key, v) )
  291. {
  292. return v;
  293. }
  294. else
  295. {
  296. std::string errorMessage = "Config: setting " + block + "::" + key + " not found !\n";
  297. errorMessage += "\n \n Config: " + help(block, key) + "\n";
  298. throw NICE::Exception( errorMessage );
  299. }
  300. }
  301. // refactor-nice.pl: check this substitution
  302. // old: string Config::gS(const string & block, const string & key, const string & defv) const
  303. std::string Config::gS(const std::string & block, const std::string & key, const std::string & defv) const
  304. {
  305. // refactor-nice.pl: check this substitution
  306. // old: string v ("");
  307. std::string v ("");
  308. if ( confS.find(block, key, v) ) {
  309. return v;
  310. } else {
  311. #if defined DEBUGCONFIG
  312. DEBUGPRINT("Config: Setting %s::%s not found using default value %s\n", block.c_str(), key.c_str(), defv.c_str() );
  313. #endif
  314. return defv;
  315. }
  316. }
  317. // refactor-nice.pl: check this substitution
  318. // old: double Config::gD(const string & key) const
  319. double Config::gD(const std::string & key) const
  320. {
  321. return gD(key, "main");
  322. }
  323. // refactor-nice.pl: check this substitution
  324. // old: double Config::gD(const string & block, const string & key) const
  325. double Config::gD(const std::string & block, const std::string & key) const
  326. {
  327. double v = 0.0;
  328. if ( confD.find(block, key, v) ) {
  329. return v;
  330. } else {
  331. int vi;
  332. if ( confI.find(block, key, vi) ) {
  333. DEBUGPRINT("Config: Setting %s::%s should be double (please change in the config)\n", block.c_str(), key.c_str() );
  334. return (int)vi;
  335. }
  336. fprintf (stderr, "Config: setting %s::%s not found !\n", block.c_str(), key.c_str() );
  337. fprintf (stderr, "Config: %s\n", help(block, key).c_str() );
  338. exit(-1);
  339. return -1.0; // never reached
  340. }
  341. }
  342. // refactor-nice.pl: check this substitution
  343. // old: double Config::gD(const string & block, const string & key, const double defv) const
  344. double Config::gD(const std::string & block, const std::string & key, const double defv) const
  345. {
  346. double v = 0.0;
  347. if ( confD.find(block, key, v) ) {
  348. return v;
  349. } else {
  350. int vi;
  351. if ( confI.find(block, key, vi) ) {
  352. DEBUGPRINT("Config: Setting %s::%s should be double (please change in the config)\n", block.c_str(), key.c_str() );
  353. return (int)vi;
  354. }
  355. #if defined DEBUGCONFIG
  356. DEBUGPRINT("Config: Setting %s::%s not found using default value %f\n", block.c_str(), key.c_str(), defv );
  357. #endif
  358. return defv;
  359. }
  360. }
  361. // refactor-nice.pl: check this substitution
  362. // old: int Config::gI(const string & key) const
  363. int Config::gI(const std::string & key) const
  364. {
  365. return gI(key, "main");
  366. }
  367. // refactor-nice.pl: check this substitution
  368. // old: int Config::gI(const string & block, const string & key) const
  369. int Config::gI(const std::string & block, const std::string & key) const
  370. {
  371. int v = 0;
  372. if ( confI.find(block, key, v) ) {
  373. return v;
  374. } else {
  375. fprintf (stderr, "Config: setting %s::%s not found !\n", block.c_str(), key.c_str() );
  376. fprintf (stderr, "Config: %s\n", help(block, key).c_str() );
  377. exit(-1);
  378. return 1; // never reached
  379. }
  380. }
  381. // refactor-nice.pl: check this substitution
  382. // old: int Config::gI(const string & block, const string & key, int defv) const
  383. int Config::gI(const std::string & block, const std::string & key, int defv) const
  384. {
  385. int v = 0;
  386. if ( confI.find(block, key, v) ) {
  387. return v;
  388. } else {
  389. #if defined DEBUGCONFIG
  390. DEBUGPRINT("Config: Setting %s::%s not found using default value %d\n", block.c_str(), key.c_str(), defv );
  391. #endif
  392. return defv;
  393. }
  394. }
  395. // refactor-nice.pl: check this substitution
  396. // old: bool Config::gB(const string & key) const
  397. bool Config::gB(const std::string & key) const
  398. {
  399. return gB(key, "main");
  400. }
  401. // refactor-nice.pl: check this substitution
  402. // old: bool Config::gB(const string & block, const string & key) const
  403. bool Config::gB(const std::string & block, const std::string & key) const
  404. {
  405. bool v = true;
  406. if ( confB.find(block, key, v) ) {
  407. return v;
  408. } else {
  409. fprintf (stderr, "Config: setting %s::%s not found !\n", block.c_str(), key.c_str() );
  410. fprintf (stderr, "Config: %s\n", help(block, key).c_str() );
  411. exit(-1);
  412. return true; // never reached
  413. }
  414. }
  415. // refactor-nice.pl: check this substitution
  416. // old: bool Config::gB(const string & block, const string & key, bool defv) const
  417. bool Config::gB(const std::string & block, const std::string & key, bool defv) const
  418. {
  419. bool v = true;
  420. if ( confB.find(block, key, v) ) {
  421. return v;
  422. } else {
  423. #if defined DEBUGCONFIG
  424. DEBUGPRINT("Config: Setting %s::%s not found using default value %d\n", block.c_str(), key.c_str(), defv );
  425. #endif
  426. return defv;
  427. }
  428. }
  429. // refactor-nice.pl: check this substitution
  430. // old: void Config::getAllS ( const std::string & block, std::map< string, string > & list ) const
  431. void Config::getAllS ( const std::string & block, std::map< string, std::string > & list ) const
  432. {
  433. confS.getAll ( block, list );
  434. }
  435. void Config::getAllD ( const std::string & block, std::map< string, double > & list ) const
  436. {
  437. confD.getAll ( block, list );
  438. }
  439. void Config::getAllI ( const std::string & block, std::map< string, int > & list ) const
  440. {
  441. confI.getAll ( block, list );
  442. }
  443. void Config::getAllB ( const std::string & block, std::map< string, bool > & list ) const
  444. {
  445. confB.getAll ( block, list );
  446. }
  447. void Config::sD(const std::string & block, const std::string & key, const double defv)
  448. {
  449. confD.store ( block, key, defv );
  450. }
  451. void Config::sI(const std::string & block, const std::string & key, const int defv)
  452. {
  453. confI.store ( block, key, defv );
  454. }
  455. void Config::sB(const std::string & block, const std::string & key, const bool defv)
  456. {
  457. confB.store ( block, key, defv );
  458. }
  459. void Config::sS(const std::string & block, const std::string & key, const std::string & defv)
  460. {
  461. confS.store ( block, key, defv );
  462. }
  463. void Config::store (ostream & os, int format) const
  464. {
  465. if (!ioUntilEndOfFile)
  466. {
  467. //let's give us a hint that we do not have to restore until end of file but until "Config::store--done"
  468. os << "Config::store--PreciseTermination" << std::endl;
  469. }
  470. os << "# -----------------------------------------" << endl;
  471. os << "# | Config |" << endl;
  472. os << "# -----------------------------------------" << endl;
  473. os << endl << "# ------------- double values" << endl;
  474. confD.store( os, format );
  475. os << endl << "# ------------- boolean values" << endl;
  476. confB.store( os, format );
  477. os << endl << "# ------------- integer values" << endl;
  478. confI.store( os, format );
  479. os << endl << "# ------------- string values" << endl;
  480. confS.store( os, format );
  481. os << "# -----------------------------------------" << endl;
  482. if (!ioUntilEndOfFile)
  483. {
  484. os << "Config::store--done" << std::endl;
  485. }
  486. }
  487. void Config::getAllBlocks ( std::set< std::string > & list ) const
  488. {
  489. list.clear();
  490. confB.getAllBlocks ( list );
  491. confD.getAllBlocks ( list );
  492. confS.getAllBlocks ( list );
  493. confI.getAllBlocks ( list );
  494. }
  495. string Config::getAbsoluteFilenameRelativeToThisConfig(const string &p_Filename) const
  496. {
  497. if( m_sConfigFilename.empty() )
  498. return p_Filename;
  499. NICE::FileName t_DatasetFilename( p_Filename );
  500. if( !t_DatasetFilename.isRelative() )
  501. {
  502. return p_Filename;
  503. }
  504. NICE::FileName t_ConfigFilename( this->m_sConfigFilename );
  505. return t_ConfigFilename.extractPath().str() + p_Filename;
  506. }