#include #include #include "Config.h" #include "ossettings.h" #include "StringTools.h" using namespace NICE; using namespace std; #undef DEBUGCONFIG #define DEBUGPRINT printf Config::Config () { ioUntilEndOfFile = true; } Config::Config ( const std::string & configfn ) { if ( configfn.size() >0 ) { read(configfn); } ioUntilEndOfFile = true; } Config::Config ( int argc, char **argv ) { readFromArguments ( argc, argv ); std::string configfile = gS("main", "config", "" ); std::cerr << "configfile: " << configfile << std::endl; ioUntilEndOfFile = gB("main", "ioUntilEndOfFile", true ); if ( configfile.size() > 0 ) readWithoutOverwrite ( configfile.c_str(), CONFIG_DO_NOT_OVERWRITE_VALUES /*do not overwrite values*/ ); } Config::Config ( const Config & conf ) : Persistent() { ioUntilEndOfFile = true; confB.copyFrom ( conf.confB ); confD.copyFrom ( conf.confD ); confI.copyFrom ( conf.confI ); confS.copyFrom ( conf.confS ); } Config::~Config() { } void Config::clear() { #if defined DEBUGCONFIG DEBUGPRINT( "Config: clear ...\n" ); #endif confB.clear(); confD.clear(); confI.clear(); confS.clear(); } void Config::addKeyValuePair ( const std::string & block, const std::string & key, const std::string & value ) { vector submatches; #if defined DEBUGCONFIG DEBUGPRINT( "Config: analyzing value %s\n", value.c_str() ); #endif if ( StringTools::regexMatch ( value, "^ *([-[:digit:]]+) *;?$", submatches ) && (submatches.size() == 2) ) { #if defined DEBUGCONFIG DEBUGPRINT ( "Config: integer value\n"); #endif int v; v = StringTools::convert ( submatches[1] ); confI.store ( block, key, v ); } else if ( value.compare("true") == 0 ) { #if defined DEBUGCONFIG DEBUGPRINT( "Config: boolean value\n"); #endif confB.store ( block, key, true ); } else if ( value.compare("false") == 0 ) { #if defined DEBUGCONFIG DEBUGPRINT ( "Config: boolean value\n"); #endif confB.store ( block, key, false ); } else if ( StringTools::regexMatch ( value, "^ *([-e.[:digit:]]+) *;?$", submatches ) && (submatches.size() == 2) ) { double v; if ( ! StringTools::convert ( submatches[1], v ) ) { DEBUGPRINT ( "Config: please ask Erik to debug this part of Config.cpp\n"); exit(-1); } #if defined DEBUGCONFIG DEBUGPRINT ( "Config: double value\n"); #endif confD.store ( block, key, v ); } else { #if defined DEBUGCONFIG DEBUGPRINT ( "Config: string value\n"); #endif string trimValue = value; StringTools::trimbounds ( trimValue, '\"' ); StringTools::trimbounds ( trimValue, '\'' ); confS.store ( block, key, trimValue ); } } void Config::readFromArguments ( int argc, char **argv ) { std::string section; std::string key; std::string value; ioUntilEndOfFile = true; for ( int i = 1 ; i < argc ; i++ ) { if ( argv[i] == NULL ) break; std::string arg ( argv[i] ); vector submatches; bool match = false; match = StringTools::regexMatch ( arg, "^--?([[:alpha:]][[:alpha:][:digit:]_-]*):([[:alpha:][:digit:]_-]+)", submatches ); if ( (match) && (submatches.size() == 3) ) { if ( key.size() > 0 ) { addArgBoolean ( section, key ); } section = submatches[1]; key = submatches[2]; continue; } match = StringTools::regexMatch ( arg, "^--?([[:alpha:]][[:alpha:][:digit:]_-]*)", submatches ); if ( (match) && (submatches.size() == 2) ) { if ( key.size() > 0 ) { addArgBoolean ( section, key ); } section = "main"; key = submatches[1]; continue; } value = string(argv[i]); if ( key.size() <= 0 ) { // add to more options moreOptions.push_back ( value ); continue; } #if defined DEBUGCONFIG cout << "Config: add command line option: " << section << ":" << key << " = " << value << endl; #endif addKeyValuePair ( section, key, value ); key = ""; } if ( key.size() > 0 ) addArgBoolean ( section, key ); } // refactor-nice.pl: check this substitution // old: void Config::addArgBoolean ( const string & section, const string & key ) void Config::addArgBoolean ( const std::string & section, const std::string & key ) { vector submatches; if ( StringTools::regexMatch ( key, "^no-(.*)$", submatches ) && (submatches.size() == 2) ) { confB.store ( section, submatches[1], false ); } else { confB.store ( section, key, true ); } } void Config::restore (istream & is, int format) { std::string block = "main"; std::string key; std::string value; std::string line; int count = 0; //check for the first word //if this is "Config::store--PreciseTermination" then we do not read until eof //but bis the precise termination statement "Config::store--done" arises std::string firstWord; if (! is.eof() ) { is >> firstWord; if ( firstWord.compare( "Config::store--PreciseTermination" ) == 0) { ioUntilEndOfFile = false; } else ioUntilEndOfFile = true; } //jump to the beginning of the file is.clear(); is.seekg(0, ios::beg); //we keep the while-loop untached, but break out of ioUntilEndOfFile is false and we reached the termination-statement while (! is.eof()) { size_t i=0; if ( !getline(is, line) ) break; //do we have to check for the precise termination statement and reaches it yet? if ( (!ioUntilEndOfFile) && (line.compare("Config::store--done") == 0) ) break; if ( line.size() <= 0 ) continue; size_t len = line.size(); count++; if ( (len < 1) || (line[0] == '#' ) ) continue; line = StringTools::chomp ( line ); len = line.size(); #if defined DEBUGCONFIG DEBUGPRINT ("Config: (%d) '%s' (len = %d) / %s\n", (int)count, line.c_str(), (int)len, block.c_str()); #endif while ( ( (line[i] == '\t') || (line[i]==' ') ) && (i= len-1) || (p<=i) ) continue; key = line.substr( i, p-i ); value = line.substr( p+1 ); // with only one argument, substr copies from the specified position until the end of the string StringTools::normalize_string(value); StringTools::normalize_string(key); // transform(key.begin(), key.end(), key.begin(), ::tolower); #if defined DEBUGCONFIG DEBUGPRINT ("Config: found key value pair (%s,%s) in section %s\n", key.c_str(), value.c_str(), block.c_str()); #endif if ( (format == CONFIG_OVERWRITE_VALUES) || ( !keyExists(block, key) ) ) addKeyValuePair ( block, key, value ); } #if defined DEBUGCONFIG DEBUGPRINT ("Config: successfully loaded.\n" ); DEBUGPRINT ("Config: %d double values\n", (int)confD.size() ); DEBUGPRINT ("Config: %d integer values\n", (int)confI.size() ); DEBUGPRINT ("Config: %d bool values\n", (int)confB.size() ); // refactor-nice.pl: check this substitution // old: DEBUGPRINT ("Config: %d string values\n", (int)confS.size() ); DEBUGPRINT ("Config: %d std::string values\n", (int)confS.size() ); #endif } bool Config::keyExists ( const std::string & block, const std::string & key ) const { return ( confS.keyExists ( block, key ) || confI.keyExists ( block, key ) || confB.keyExists ( block, key ) || confD.keyExists ( block, key ) ); } void Config::addHelp ( const std::string & block, const std::string & key, const std::string & helpText ) { helpTexts[ block + "::" + key ] = helpText; } std::string Config::help ( const std::string & block, const std::string & key ) const { std::string k = block + "::" + key; map::const_iterator i = helpTexts.find(k); if ( i == helpTexts.end() ) return "no helping information for this variable, sorry!"; else return i->second; } std::string Config::gS(const std::string & key) const { return gS(key, "main"); } std::string Config::gS(const std::string & block, const std::string & key) const { std::string v (""); if ( confS.find(block, key, v) ) { return v; } else { fprintf (stderr, "Config: setting %s::%s not found !\n", block.c_str(), key.c_str() ); fprintf (stderr, "Config: %s\n", help(block, key).c_str() ); exit(-1); return ""; // never reached } } // refactor-nice.pl: check this substitution // old: string Config::gS(const string & block, const string & key, const string & defv) const std::string Config::gS(const std::string & block, const std::string & key, const std::string & defv) const { // refactor-nice.pl: check this substitution // old: string v (""); std::string v (""); if ( confS.find(block, key, v) ) { return v; } else { #if defined DEBUGCONFIG DEBUGPRINT("Config: Setting %s::%s not found using default value %s\n", block.c_str(), key.c_str(), defv.c_str() ); #endif return defv; } } // refactor-nice.pl: check this substitution // old: double Config::gD(const string & key) const double Config::gD(const std::string & key) const { return gD(key, "main"); } // refactor-nice.pl: check this substitution // old: double Config::gD(const string & block, const string & key) const double Config::gD(const std::string & block, const std::string & key) const { double v = 0.0; if ( confD.find(block, key, v) ) { return v; } else { int vi; if ( confI.find(block, key, vi) ) { DEBUGPRINT("Config: Setting %s::%s should be double (please change in the config)\n", block.c_str(), key.c_str() ); return (int)vi; } fprintf (stderr, "Config: setting %s::%s not found !\n", block.c_str(), key.c_str() ); fprintf (stderr, "Config: %s\n", help(block, key).c_str() ); exit(-1); return -1.0; // never reached } } // refactor-nice.pl: check this substitution // old: double Config::gD(const string & block, const string & key, const double defv) const double Config::gD(const std::string & block, const std::string & key, const double defv) const { double v = 0.0; if ( confD.find(block, key, v) ) { return v; } else { int vi; if ( confI.find(block, key, vi) ) { DEBUGPRINT("Config: Setting %s::%s should be double (please change in the config)\n", block.c_str(), key.c_str() ); return (int)vi; } #if defined DEBUGCONFIG DEBUGPRINT("Config: Setting %s::%s not found using default value %f\n", block.c_str(), key.c_str(), defv ); #endif return defv; } } // refactor-nice.pl: check this substitution // old: int Config::gI(const string & key) const int Config::gI(const std::string & key) const { return gI(key, "main"); } // refactor-nice.pl: check this substitution // old: int Config::gI(const string & block, const string & key) const int Config::gI(const std::string & block, const std::string & key) const { int v = 0; if ( confI.find(block, key, v) ) { return v; } else { fprintf (stderr, "Config: setting %s::%s not found !\n", block.c_str(), key.c_str() ); fprintf (stderr, "Config: %s\n", help(block, key).c_str() ); exit(-1); return 1; // never reached } } // refactor-nice.pl: check this substitution // old: int Config::gI(const string & block, const string & key, int defv) const int Config::gI(const std::string & block, const std::string & key, int defv) const { int v = 0; if ( confI.find(block, key, v) ) { return v; } else { #if defined DEBUGCONFIG DEBUGPRINT("Config: Setting %s::%s not found using default value %d\n", block.c_str(), key.c_str(), defv ); #endif return defv; } } // refactor-nice.pl: check this substitution // old: bool Config::gB(const string & key) const bool Config::gB(const std::string & key) const { return gB(key, "main"); } // refactor-nice.pl: check this substitution // old: bool Config::gB(const string & block, const string & key) const bool Config::gB(const std::string & block, const std::string & key) const { bool v = true; if ( confB.find(block, key, v) ) { return v; } else { fprintf (stderr, "Config: setting %s::%s not found !\n", block.c_str(), key.c_str() ); fprintf (stderr, "Config: %s\n", help(block, key).c_str() ); exit(-1); return true; // never reached } } // refactor-nice.pl: check this substitution // old: bool Config::gB(const string & block, const string & key, bool defv) const bool Config::gB(const std::string & block, const std::string & key, bool defv) const { bool v = true; if ( confB.find(block, key, v) ) { return v; } else { #if defined DEBUGCONFIG DEBUGPRINT("Config: Setting %s::%s not found using default value %d\n", block.c_str(), key.c_str(), defv ); #endif return defv; } } // refactor-nice.pl: check this substitution // old: void Config::getAllS ( const std::string & block, std::map< string, string > & list ) const void Config::getAllS ( const std::string & block, std::map< string, std::string > & list ) const { confS.getAll ( block, list ); } void Config::getAllD ( const std::string & block, std::map< string, double > & list ) const { confD.getAll ( block, list ); } void Config::getAllI ( const std::string & block, std::map< string, int > & list ) const { confI.getAll ( block, list ); } void Config::getAllB ( const std::string & block, std::map< string, bool > & list ) const { confB.getAll ( block, list ); } void Config::sD(const std::string & block, const std::string & key, const double defv) { confD.store ( block, key, defv ); } void Config::sI(const std::string & block, const std::string & key, const int defv) { confI.store ( block, key, defv ); } void Config::sB(const std::string & block, const std::string & key, const bool defv) { confB.store ( block, key, defv ); } void Config::sS(const std::string & block, const std::string & key, const std::string & defv) { confS.store ( block, key, defv ); } void Config::store (ostream & os, int format) const { if (!ioUntilEndOfFile) { //let's give us a hint that we do not have to restore until end of file but until "Config::store--done" os << "Config::store--PreciseTermination" << std::endl; } os << "# -----------------------------------------" << endl; os << "# | Config |" << endl; os << "# -----------------------------------------" << endl; os << endl << "# ------------- double values" << endl; confD.store( os, format ); os << endl << "# ------------- boolean values" << endl; confB.store( os, format ); os << endl << "# ------------- integer values" << endl; confI.store( os, format ); os << endl << "# ------------- string values" << endl; confS.store( os, format ); os << "# -----------------------------------------" << endl; if (!ioUntilEndOfFile) { os << "Config::store--done" << std::endl; } } void Config::getAllBlocks ( std::set< std::string > & list ) const { list.clear(); confB.getAllBlocks ( list ); confD.getAllBlocks ( list ); confS.getAllBlocks ( list ); confI.getAllBlocks ( list ); }