// Description: // Keeps track of configurable values. // // Copyright (C) 2001 Frank Becker // // This program is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free Software // Foundation; either version 2 of the License, or (at your option) any later // version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details // #include #include #include #include #include #include #include #include const string CONFIG_DEFAULT_FILE1 = "config.txt"; Config::Config( void): _defaultConfigFileName(".critter") { XTRACE(); } Config::~Config() { XTRACE(); hash_map >::const_iterator ci; for( ci=_keyValueMap.begin(); ci!=_keyValueMap.end(); ci++) { delete ci->second; } _keyValueMap.clear(); for( ci=_keyValueMapTrans.begin(); ci!=_keyValueMapTrans.end(); ci++) { delete ci->second; } _keyValueMapTrans.clear(); } void Config::getConfigItemList( list &ciList) { hash_map >::const_iterator ci; for( ci=_keyValueMap.begin(); ci!=_keyValueMap.end(); ci++) { ConfigItem item; item.key = ci->first; item.value = ci->second->getString(); ciList.insert( ciList.begin(), item); } } const string &Config::getConfigFileName( void) { struct stat statInfo; static string configFile; getString( CONFIGFILE, configFile); static string CONFIG_DEFAULT_FILE2 = _defaultConfigFileName; //does explicitly given config file exist? if( configFile == "") { if( (stat( CONFIG_DEFAULT_FILE1.c_str(), &statInfo) != -1) ) { //local config.txt exists -> OK return CONFIG_DEFAULT_FILE1; } if( (stat( CONFIG_DEFAULT_FILE2.c_str(), &statInfo) != -1) ) { //local .file exists -> OK return CONFIG_DEFAULT_FILE2; } #ifdef WIN32 configFile = CONFIG_DEFAULT_FILE1; #else const char * home = getenv("HOME"); if( home) { configFile = home; configFile += "/" + CONFIG_DEFAULT_FILE2; } #endif } else { if( (stat( configFile.c_str(), &statInfo) != -1) ) { //local config exists -> OK return configFile; } #ifndef WIN32 const char * home = getenv("HOME"); if( home) { string homeConfig = home; homeConfig += "/" + configFile; if( (stat( homeConfig.c_str(), &statInfo) != -1) ) { //home config exists -> OK configFile = homeConfig; return configFile; } } #endif } return configFile; } void Config::updateFromCommandLine( int argc, char *argv[]) { XTRACE(); for( int i=1; iselectResource( configFile)) { string systemConfigFile = "system/config.txt"; if( !ResourceManagerS::instance()->selectResource( systemConfigFile)) { LOG_ERROR << "System Config file not found!" << endl; return; } LOG_WARNING << "Config file [" << configFile << "] not found, using default." << endl; } ziStream &infile = ResourceManagerS::instance()->getInputStream(); string line; while( !getline( infile, line).eof()) { // LOG_INFO << "[" << line << "]" << endl; //explicitly skip comments if( line[0] == '#') continue; list::iterator i; for( i=_configHandlerList.begin(); i!=_configHandlerList.end(); i++) { ConfigHandler *ch = *i; ch->handleLine( line); } Tokenizer t( line, " \t\n\r="); string setKeyname = t.next(); if( setKeyname == "set") { string keyword = t.next(); string value = t.next(); // LOG_INFO << "Keyword [" << keyword << "] = [" // << value << "]" << endl; updateKeyword( keyword, value); } } } void Config::updateTransitoryKeyword( const char *keyword, const char *value) { XTRACE(); if( keyword && value) { string tmpKeyword( keyword); string tmpValue( value); removeTrans( tmpKeyword); _keyValueMapTrans[ tmpKeyword] = new Value( tmpValue); } } void Config::updateKeyword( const char *keyword, const char *value) { XTRACE(); if( keyword && value) { string tmpKeyword( keyword); string tmpValue( value); remove( tmpKeyword); _keyValueMap[ tmpKeyword] = new Value( tmpValue); } } void Config::updateKeyword( const string keyword, const string value) { XTRACE(); remove( keyword); _keyValueMap[ keyword] = new Value( value); } void Config::updateKeyword( const string keyword, Value *value) { XTRACE(); remove( keyword); _keyValueMap[ keyword] = value; } void Config::remove( const string &keyword) { removeImpl(keyword, _keyValueMap); } void Config::removeTrans( const string &keyword) { removeImpl(keyword, _keyValueMapTrans); } void Config::removeImpl( const string &keyword, hash_map< string, Value*, hash, equal_to > &kvmap) { hash_map >::iterator ci; ci = kvmap.find( keyword); if( ci!=kvmap.end()) { delete ci->second; kvmap.erase( ci); } } void Config::saveToFile( bool truncate) { XTRACE(); const string configFile = getConfigFileName(); LOG_INFO << "Saving Configuration to : " << configFile << endl; ios::openmode om = ios::out | ios::app; if( truncate) { om = ios::out | ios::trunc; } ofstream outfile( configFile.c_str(), om); outfile << "# This is a generated file. Edit carefully!" << endl; outfile << "# --- Variable section --- " << endl; hash_map >::const_iterator ci; for( ci=_keyValueMap.begin(); ci!=_keyValueMap.end(); ci++) { Value *val = ci->second; if( val) { string v = val->getString(); if( v.find_first_of(" \t") != string::npos) { //value contains whitespace outfile << "set " << ci->first << " = \"" << v << "\"" << endl; } else { outfile << "set " << ci->first << " = " << v << endl; } } else { LOG_WARNING << "No value for key [" << ci->first << "]" << endl; } } list::iterator i; for( i=_configHandlerList.begin(); i!=_configHandlerList.end(); i++) { ConfigHandler *ch = *i; ch->save( outfile); } } bool Config::getString( const string &keyword, string &value) { XTRACE(); if( getStringImpl(keyword,value,_keyValueMapTrans)) return true; return getStringImpl(keyword,value,_keyValueMap); } bool Config::getInteger( const string &keyword, int &value) { XTRACE(); if( getIntegerImpl(keyword,value,_keyValueMapTrans)) return true; return getIntegerImpl(keyword,value,_keyValueMap); } bool Config::getBoolean( const string &keyword, bool &value) { XTRACE(); if( getBooleanImpl(keyword,value,_keyValueMapTrans)) return true; return getBooleanImpl(keyword,value,_keyValueMap); } bool Config::getFloat( const string &keyword, float &value) { XTRACE(); if( getFloatImpl(keyword,value,_keyValueMapTrans)) return true; return getFloatImpl(keyword,value,_keyValueMap); } bool Config::getStringImpl( const string &keyword, string &value, hash_map< string, Value*, hash, equal_to > &kvmap) { hash_map >::const_iterator ci; ci = kvmap.find( keyword); if( ci!=kvmap.end()) { value = ci->second->getString(); return true; } return false; } bool Config::getIntegerImpl( const string &keyword, int &value, hash_map< string, Value*, hash, equal_to > &kvmap) { hash_map >::const_iterator ci; ci = kvmap.find( keyword); if( ci!=kvmap.end()) { value = ci->second->getInteger(); return true; } return false; } bool Config::getBooleanImpl( const string &keyword, bool &value, hash_map< string, Value*, hash, equal_to > &kvmap) { hash_map >::const_iterator ci; ci = kvmap.find( keyword); if( ci!=kvmap.end()) { value = ci->second->getBoolean(); return true; } return false; } bool Config::getFloatImpl( const string &keyword, float &value, hash_map< string, Value*, hash, equal_to > &kvmap) { hash_map >::const_iterator ci; ci = kvmap.find( keyword); if( ci!=kvmap.end()) { value = ci->second->getFloat(); return true; } return false; } void Config::dump( void) { XTRACE(); hash_map >::const_iterator ci; for( ci=_keyValueMap.begin(); ci!=_keyValueMap.end(); ci++) { Value *val = ci->second; if( val) LOG_INFO << ci->first << " = " << val->dump() << endl; else LOG_INFO << ci->first << endl; } }