00001 #include <string>
00002 #include <stdlib.h>
00003 #include <fstream>
00004 #include "engine/mutex.h"
00005 #include "log.h"
00006 #include "conversion.h"
00007 #include "conf_impl.h"
00008
00009 ConfigImpl::ConfigImpl() : Mutex(RECURSIVE_MUTEX)
00010 {
00011 Lock();
00012 loaded = false;
00013 Unlock();
00014 }
00015
00016 static ssize_t getline(std::string &line, std::ifstream& file)
00017 {
00018 line.clear();
00019 std::getline(file, line);
00020 if(file.eof())
00021 return -1;
00022 return line.size();
00023 }
00024
00025 void ConfigImpl::Parse(std::string line)
00026 {
00027 Lock();
00028 std::string::size_type equ_pos = line.find('=',0);
00029 if(equ_pos == std::string::npos)
00030 {
00031 fprintf(stderr ,"Badly formated option on command line: %s\n", line.c_str());
00032 Unlock();
00033 return;
00034 }
00035
00036 std::string opt = line.substr(0, equ_pos);
00037 std::string val = line.substr(equ_pos+1);
00038
00039
00040 size_t comma_pos = 0;
00041 size_t last_comma = 0;
00042 while(true)
00043 {
00044
00045 while(comma_pos != std::string::npos && (comma_pos == last_comma || (comma_pos != 0 && val[comma_pos - 1] == '\\')))
00046 {
00047 if(comma_pos != 0 && val[comma_pos - 1] == '\\')
00048 comma_pos ++;
00049 comma_pos = val.find(',', comma_pos);
00050 }
00051
00052 std::string subval;
00053 if(comma_pos != std::string::npos)
00054 subval = val.substr(last_comma, comma_pos - last_comma);
00055 else
00056 subval = val.substr(last_comma);
00057
00058
00059 size_t bs = subval.find('\\', 0);
00060 while(bs != std::string::npos)
00061 {
00062 if(bs < subval.size() - 1 && subval[bs + 1] == ',')
00063 subval.replace(bs, 1, "");
00064 else
00065 bs++;
00066 bs = subval.find('\\', bs);
00067 }
00068
00069 bool is_list = !(last_comma == 0 && comma_pos == std::string::npos);
00070
00071
00072 if(subval != "" && subval.find('.',0) == std::string::npos
00073 && (subval.at(0) >= '0' && subval.at(0) <= '9'))
00074 {
00075 int nbr = atoi(subval.c_str());
00076 if(is_list)
00077 {
00078 if(int_list_value.find(opt) == int_list_value.end())
00079 int_list_value[ opt ] = std::list<int>();
00080 int_list_value[ opt ].push_back(nbr);
00081 }
00082 else
00083 int_value[ opt ] = nbr;
00084 }
00085 else
00086 {
00087 if(subval == "true")
00088 bool_value[ opt ] = true;
00089 else
00090 if(subval == "false")
00091 bool_value[ opt ] = false;
00092 else
00093 {
00094 if(is_list)
00095 {
00096 if(str_list_value.find(opt) == str_list_value.end())
00097 str_list_value[ opt ] = std::list<std::string>();
00098 str_list_value[ opt ].push_back(subval);
00099 }
00100 else
00101 str_value[ opt ] = subval;
00102 }
00103 }
00104 if(comma_pos == std::string::npos)
00105 break;
00106 comma_pos++;
00107 last_comma = comma_pos;
00108 }
00109 Unlock();
00110 }
00111
00112 void ConfigImpl::Load(std::string _file)
00113 {
00114 Lock();
00115 log(LogInfo, "Loading config file %s", _file.c_str());
00116 int line_nbr = 0;
00117 loaded = true;
00118
00119
00120 std::ifstream fin;
00121 fin.open(_file.c_str(), std::ios::in);
00122 if(!fin)
00123 {
00124 fprintf(stderr, "Unable to open config file %s\n", _file.c_str());
00125 Unlock();
00126 return;
00127 }
00128
00129 ssize_t read;
00130 std::string line;
00131
00132 while ((read = getline(line, fin)) >= 0)
00133 {
00134 line_nbr++;
00135 if(line.size() == 0 || line.at(0) == '#' )
00136 continue;
00137
00138 std::string::size_type equ_pos = line.find('=',0);
00139 if(equ_pos == std::string::npos)
00140 {
00141 fprintf(stderr, "Wrong format on line %i\n",line_nbr);
00142 continue;
00143 }
00144
00145 Parse(line);
00146 }
00147 Unlock();
00148 }
00149
00150 std::string escape(std::string str)
00151 {
00152 size_t pos = str.find(',');
00153 while(pos != std::string::npos)
00154 {
00155 std::string new_str = str.substr(0, pos) + std::string("\\") + str.substr(pos);
00156 pos = new_str.find(',', pos + 2);
00157 str = new_str;
00158 }
00159 return str;
00160 }
00161
00162 std::string ConfigImpl::GetAsString()
00163 {
00164 Lock();
00165 std::string str = "";
00166
00167
00168 for(std::map<std::string, bool>::iterator cfg = bool_value.begin();
00169 cfg != bool_value.end();
00170 ++cfg)
00171 str += cfg->first + std::string(cfg->second ? "=true\n" : "=false\n");
00172
00173 for(std::map<std::string, int>::iterator cfg = int_value.begin();
00174 cfg != int_value.end();
00175 ++cfg)
00176 str += cfg->first + std::string("=") + int2str(cfg->second) + std::string("\n");
00177
00178 for(std::map<std::string, std::string>::iterator cfg = str_value.begin();
00179 cfg != str_value.end();
00180 ++cfg)
00181 str += cfg->first + std::string("=") + escape(cfg->second) + std::string("\n");
00182
00183
00184 for(std::map<std::string, std::list<std::string> >::iterator cfg = str_list_value.begin();
00185 cfg != str_list_value.end();
00186 ++cfg)
00187 {
00188 str += cfg->first + std::string("=");
00189
00190 unsigned int i = 0;
00191 for(std::list<std::string>::iterator it = cfg->second.begin();
00192 it != cfg->second.end();
00193 ++it, ++i)
00194 {
00195 str += escape(*it);
00196 if(i != cfg->second.size() - 1)
00197 str += std::string(",");
00198 }
00199 str += std::string("\n");
00200 }
00201
00202
00203 for(std::map<std::string, std::list<int> >::iterator cfg = int_list_value.begin();
00204 cfg != int_list_value.end();
00205 ++cfg)
00206 {
00207 str += cfg->first + std::string("=");
00208
00209 unsigned int i = 0;
00210 for(std::list<int>::iterator it = cfg->second.begin();
00211 it != cfg->second.end();
00212 ++it, ++i)
00213 {
00214 str += int2str(*it);
00215 if(i != cfg->second.size() - 1)
00216 str += std::string(",");
00217 }
00218 str += std::string("\n");
00219 }
00220
00221 Unlock();
00222 return str;
00223 }
00224
00225 bool ConfigImpl::Get(const std::string & name, bool & value)
00226 {
00227 Lock();
00228 if( bool_value.find(name) == bool_value.end() )
00229 {
00230 Unlock();
00231 return false;
00232 }
00233
00234 value = bool_value[ name ];
00235 Unlock();
00236 return true;
00237 }
00238
00239 bool ConfigImpl::Get(const std::string & name, int & value)
00240 {
00241 Lock();
00242 if( int_value.find(name) == int_value.end() )
00243 {
00244 Unlock();
00245 return false;
00246 }
00247
00248 value = int_value[ name ];
00249 Unlock();
00250 return true;
00251 }
00252
00253 bool ConfigImpl::Get(const std::string & name, std::string & value)
00254 {
00255 Lock();
00256 if( str_value.find(name) == str_value.end() )
00257 {
00258 Unlock();
00259 return false;
00260 }
00261
00262 value = str_value[ name ];
00263 Unlock();
00264 return true;
00265 }
00266
00267 bool ConfigImpl::Get(const std::string & name, std::list<std::string> & value)
00268 {
00269 Lock();
00270 if( str_list_value.find(name) == str_list_value.end() )
00271 {
00272 std::string val;
00273 if(Get(name, val))
00274 {
00275 str_value.erase(name);
00276 str_list_value[ name ] = std::list<std::string>();
00277 str_list_value[ name ].push_back(val);
00278 }
00279 else
00280 {
00281 Unlock();
00282 return false;
00283 }
00284 }
00285
00286 value = str_list_value[ name ];
00287 Unlock();
00288 return true;
00289 }
00290
00291 bool ConfigImpl::Get(const std::string & name, std::list<int> & value)
00292 {
00293 Lock();
00294 if( int_list_value.find(name) == int_list_value.end() )
00295 {
00296 int val;
00297 if(Get(name, val))
00298 {
00299 int_value.erase(name);
00300 int_list_value[ name ] = std::list<int>();
00301 int_list_value[ name ].push_back(val);
00302 }
00303 else
00304 {
00305 Unlock();
00306 return false;
00307 }
00308 }
00309
00310 value = int_list_value[ name ];
00311 Unlock();
00312 return true;
00313 }
00314
00315 void ConfigImpl::SetDefaultBool(const std::string & name, const bool & value)
00316 {
00317 Lock();
00318 bool val;
00319 if( ! Get(name, val) )
00320 bool_value[ name ] = value;
00321 Unlock();
00322 }
00323
00324 void ConfigImpl::SetDefaultInt(const std::string & name, const int & value)
00325 {
00326 Lock();
00327 int val;
00328 if( ! Get(name, val) )
00329 int_value[ name ] = value;
00330 Unlock();
00331 }
00332
00333 void ConfigImpl::SetDefaultString(const std::string & name, const std::string & value)
00334 {
00335 Lock();
00336 std::string val;
00337 if( ! Get(name, val) )
00338 str_value[ name ] = value;
00339 Unlock();
00340 }
00341
00342 void ConfigImpl::ParseShellArgs(int argc, char** argv)
00343 {
00344 Lock();
00345 for(int no=1; no < argc; no++)
00346 Parse(std::string( (char*)argv[no] ));
00347 Unlock();
00348 }
00349
00350 void ConfigImpl::SetBool(std::string name, const bool & value)
00351 {
00352 Lock();
00353 loaded = true;
00354 bool_value[name] = value;
00355 Unlock();
00356 }
00357
00358 void ConfigImpl::SetInt(std::string name, const int & value)
00359 {
00360 Lock();
00361 loaded = true;
00362 int_value[name] = value;
00363 Unlock();
00364 }
00365
00366 void ConfigImpl::SetString(std::string name, const std::string & value)
00367 {
00368 Lock();
00369 loaded = true;
00370 str_value[name] = value;
00371 Unlock();
00372 }
00373
00374 void ConfigImpl::SetStringList(std::string name, const std::list<std::string> & value)
00375 {
00376 Lock();
00377 loaded = true;
00378 str_list_value[name] = value;
00379 Unlock();
00380 }
00381
00382 void ConfigImpl::SetIntList(std::string name, const std::list<int> & value)
00383 {
00384 Lock();
00385 loaded = true;
00386 int_list_value[name] = value;
00387 Unlock();
00388 }
00389
00390 bool ConfigImpl::IsLoaded()
00391 {
00392 Lock();
00393 bool ret = loaded;
00394 Unlock();
00395 return ret;
00396 }
00397