Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef CONFIG_H
00011 #define CONFIG_H
00012
00013 #include <iostream>
00014 #include <map>
00015 #include <set>
00016 #include <string>
00017 #include <vector>
00018 #include <assert.h>
00019 #include <cstring>
00020
00021 #include "../../Architecture/Thread/Mutex.h"
00022
00023 class TiXmlNode;
00024 class TiXmlElement;
00025
00026
00032 class Config
00033 {
00034 public:
00035 Config();
00036 Config(const Config& c2);
00037 Config& operator=(const Config& c2);
00038 ~Config();
00039
00040 static Config* getInstance();
00041 static void setInstance ( Config* newInst )
00042 {
00043
00044 Config* oldInst=m_inst;
00045 m_inst=newInst;
00046 delete oldInst;
00047
00048 };
00049
00050 static int getInt ( const std::string& id );
00051 static bool getBool ( const std::string& id );
00052 static std::string getString( const std::string& id );
00053 static float getFloat( const std::string& id );
00054
00055 static bool getFloatMinMax ( const std::string& id, std::pair<float,float>& minmax );
00056 static bool getIntMinMax ( const std::string& id, std::pair<int,int>& minmax );
00057
00063 static void loadConfig(const std::vector<std::string> files, const std::vector<std::string> profiles, const std::string& prepend_path = ".");
00064
00065
00066 template<class T>
00067 void set ( const std::string& id, T f );
00068
00069 bool loadFromFile ( const std::string& fileName, const std::vector<std::string>& profiles );
00070
00071 void clear();
00072
00073 std::vector<std::string> getAllVars() const;
00074
00075 const std::vector<std::string>& getModuleList () const;
00076
00077 void addModule( std::string name );
00078
00079 const std::string& getFilename() const;
00080
00081 std::string toText();
00082
00083 std::string getActiveProfileName() const { return m_activeProfile; }
00084
00085 std::string getAllProfileNames() { return m_allProfileNames; }
00086
00090 static Mutex m_AccessMutex;
00091 private:
00092
00093
00094 template<class T>
00095 T get ( const std::string& id ) const;
00096
00097 template<class T>
00098 bool getMinMax ( const std::string& id, std::pair<T,T>& minmax ) const;
00099
00101 std::vector<std::string> explode ( const std::string& text, const std::string& separators, bool keepSeparators=false );
00102
00103 std::string m_fileName;
00104 std::string m_activeProfile;
00105 std::vector<std::string> m_moduleList;
00106
00107 std::set<std::string> m_loadedProfileNames;
00108
00109 std::string m_allProfileNames;
00110
00111 bool parseProfile ( TiXmlNode* root );
00112 bool parseValues ( const std::string& level, TiXmlNode* root );
00113 void parseModules ( TiXmlNode* root );
00114
00115 class ConfigEntry
00116 {
00117 public:
00118 ConfigEntry() {data=0; minval=0; maxval=0; type=TYPE_INT; }
00119 ~ConfigEntry() {
00120 if ( type==TYPE_STRING ) {
00121 delete[] data;
00122 }
00123 }
00124
00125 ConfigEntry ( const ConfigEntry& e2 )
00126 {
00127 type=e2.type;
00128
00129 minval=e2.minval;
00130 maxval=e2.maxval;
00131 if ( e2.type!=TYPE_STRING )
00132 {
00133 data=e2.data;
00134 }
00135 else
00136 {
00137 data=new char[strlen ( ( const char* ) e2.data ) +1];
00138 strcpy ( ( char* ) data, ( const char* ) e2.data );
00139 }
00140 }
00141
00142 ConfigEntry& operator= ( const ConfigEntry& e2 )
00143 {
00144 type=e2.type;
00145
00146 minval=e2.minval;
00147 maxval=e2.maxval;
00148 if ( e2.type!=TYPE_STRING )
00149 {
00150 data=e2.data;
00151 }
00152 else
00153 {
00154 data=new char[strlen ( ( const char* ) e2.data ) +1];
00155 strcpy ( ( char* ) data, ( char* ) e2.data );
00156 }
00157 return ( *this );
00158 }
00159 template<class T>
00160 void set ( T t );
00161
00162 bool operator==(const ConfigEntry& e2)
00163 {
00164
00165 if (e2.type!=type) return false;
00166 if (e2.type!=TYPE_STRING)
00167 {
00168 bool ret=(e2.data==data)&&(e2.minval==minval)&&(e2.maxval==maxval);;
00169
00170 return ret;
00171 }
00172 else
00173 {
00174 if (e2.data&&data)
00175 {
00176 return !strcmp((const char*)e2.data,(const char*)data);
00177 }
00178 else return false;
00179 }
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 void setInt ( int i )
00198 {
00199 type=TYPE_INT;
00200 data_int=i;
00201 }
00202 void setIntMin ( int m )
00203 {
00204 assert ( type==TYPE_INT );
00205 minval_int=m;
00206 }
00207 void setIntMax ( int m )
00208 {
00209 assert ( type==TYPE_INT );
00210 maxval_int=m;
00211 }
00212 void setFloat ( float f )
00213 {
00214 type=TYPE_FLOAT;
00215 data_float=f;
00216 }
00217 void setFloatMin ( float m )
00218 {
00219 assert ( type==TYPE_FLOAT );
00220 minval_float=m;
00221 }
00222 void setFloatMax ( float m )
00223 {
00224 assert ( type==TYPE_FLOAT );
00225 maxval_float=m;
00226 }
00227 void setString ( const char* p )
00228 {
00229 type=TYPE_STRING;
00230 delete[] ( char* ) data;
00231 data = new char[strlen ( p ) +1];
00232 strcpy ( ( char* ) data,p );
00233 }
00234 int getInt() const
00235 {
00236 assert ( type==TYPE_INT );
00237 return data_int;
00238 }
00239 float getFloat() const
00240 {
00241 assert ( type==TYPE_FLOAT );
00242 return data_float;
00243 }
00244 const char* getString() const
00245 {
00246 assert ( type==TYPE_STRING );
00247 return ( const char* ) data;
00248 }
00249 int getIntMax() const
00250 {
00251 assert ( type==TYPE_INT );
00252 return maxval_int;
00253 }
00254 int getIntMin() const
00255 {
00256 assert ( type==TYPE_INT );
00257 return minval_int;
00258 }
00259 float getFloatMax() const
00260 {
00261 assert ( type==TYPE_FLOAT );
00262 return maxval_float;
00263 }
00264 float getFloatMin() const
00265 {
00266 assert ( type==TYPE_FLOAT );
00267 return minval_float;
00268 }
00269
00270 enum eType
00271 {
00272 TYPE_INT=1,
00273 TYPE_FLOAT,
00274 TYPE_STRING,
00275 };
00276
00277 eType getType() const
00278 {
00279 return type;
00280 }
00281
00282 private:
00283
00284 eType deduceType ( int ) const
00285 {
00286 return TYPE_INT;
00287 }
00288 eType deduceType ( const char* ) const
00289 {
00290 return TYPE_STRING;
00291 }
00292 eType deduceType ( float ) const
00293 {
00294 return TYPE_FLOAT;
00295 }
00296 eType type;
00297 union
00298 {
00299 char* data;
00300 int data_int;
00301 float data_float;
00302 };
00303 union
00304 {
00305 void* minval;
00306 int minval_int;
00307 float minval_float;
00308 };
00309 union
00310 {
00311 void* maxval;
00312 int maxval_int;
00313 float maxval_float;
00314 };
00315 };
00316
00317 bool parseValue ( TiXmlElement* el,class ConfigEntry& newEntry , std::string& name) const;
00318
00319 void saveValue ( const std::string& name, const ConfigEntry& entry, TiXmlElement* allProfValues,TiXmlElement* values ) const;
00320
00321 bool parseDocument(const std::string& fileName, const std::vector<std::string>& profiles );
00322
00323 std::map<std::string, ConfigEntry> m_values;
00324
00325 static Config* m_inst;
00326
00327 class TiXmlDocument* m_doc;
00328
00329 };
00330
00331 template<>
00332 inline void Config::ConfigEntry::set ( float t )
00333 {
00334 setFloat ( t );
00335 }
00336 template<>
00337 inline void Config::ConfigEntry::set ( int t )
00338 {
00339 setInt ( t );
00340 }
00341 template<>
00342 inline void Config::ConfigEntry::set ( const char* t )
00343 {
00344 setString ( t );
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 template<>
00382 inline float Config::get ( const std::string& id ) const
00383 {
00384 m_AccessMutex.lock ();
00385 std::map<std::string,ConfigEntry>::const_iterator it=m_values.find ( id );
00386 if ( it==m_values.end() )
00387 {
00388 std::cerr << "Config: ERROR Config value '" << id << "' not found! Exiting!" << std::endl;
00389 }
00390 assert ( it!=m_values.end() );
00391
00392 ConfigEntry::eType t=it->second.getType();
00393 if ( t!=ConfigEntry::TYPE_FLOAT )
00394 {
00395 std::cerr << "Config: ERROR Config value '" << id << "' has wrong type! Exiting!" << std::endl;
00396 }
00397 assert ( t==ConfigEntry::TYPE_FLOAT );
00398 float value=it->second.getFloat();
00399 m_AccessMutex.unlock ();
00400 return value;
00401 }
00402
00403 template<>
00404 inline int Config::get ( const std::string& id ) const
00405 {
00406 m_AccessMutex.lock ();
00407 std::map<std::string,ConfigEntry>::const_iterator it=m_values.find ( id );
00408 if ( it==m_values.end() )
00409 {
00410 std::cerr << "Config: ERROR Config value '" << id << "' not found! Exiting!" << std::endl;
00411 }
00412 assert ( it!=m_values.end() );
00413
00414 ConfigEntry::eType t=it->second.getType();
00415 if ( t!=ConfigEntry::TYPE_INT )
00416 {
00417 std::cerr << "Config: ERROR Config value '" << id << "' has wrong type! Exiting!" << std::endl;
00418 }
00419 int value=it->second.getInt();
00420 assert ( t==ConfigEntry::TYPE_INT );
00421 m_AccessMutex.unlock ();
00422 return value;
00423 }
00424
00425 template<>
00426 inline const char* Config::get ( const std::string& id ) const
00427 {
00428 m_AccessMutex.lock ();
00429 std::map<std::string,ConfigEntry>::const_iterator it=m_values.find ( id );
00430 if ( it==m_values.end() )
00431 {
00432 std::cerr << "Config: ERROR Config value '" << id << "' not found! Exiting!" << std::endl;
00433 }
00434 assert ( it!=m_values.end() );
00435
00436 ConfigEntry::eType t=it->second.getType();
00437 if ( t!=ConfigEntry::TYPE_STRING )
00438 {
00439 std::cerr << "Config: ERROR Config value '" << id << "' has wrong type! Exiting!" << std::endl;
00440 }
00441 assert ( t==ConfigEntry::TYPE_STRING );
00442 const char* value=it->second.getString();
00443 m_AccessMutex.unlock ();
00444 return value;
00445 }
00446
00447 template<>
00448 inline std::string Config::get ( const std::string& id ) const
00449 {
00450 return get<const char*>(id);
00451 }
00452
00453 template<class T>
00454 void Config::set ( const std::string& id, T f )
00455 {
00456
00457
00458
00459
00460
00461
00462 m_AccessMutex.lock ();
00463 m_values[id].set<T> ( f );
00464 m_AccessMutex.unlock ();
00465 }
00466
00467
00468 template<class T>
00469 bool Config::getMinMax ( const std::string& id, std::pair<T,T>& minmax ) const
00470 {
00471 std::map<std::string,ConfigEntry>::const_iterator it=m_values.find ( id );
00472 if ( it==m_values.end() )
00473 {
00474 std::cerr << "Config: ERROR Config value '" << id << "' not found! Exiting!" << std::endl;
00475 }
00476 assert ( it!=m_values.end() );
00477
00478 ConfigEntry::eType t=it->second.getType();
00479 if ( t==ConfigEntry::TYPE_INT )
00480 {
00481 int mi=it->second.getIntMin();
00482 int ma=it->second.getIntMax();
00483 if ( mi==ma ) return false;
00484 minmax=std::make_pair ( mi,ma );
00485 return true;
00486 }
00487 else if ( t==ConfigEntry::TYPE_FLOAT )
00488 {
00489 float mi=it->second.getFloatMin();
00490 float ma=it->second.getFloatMax();
00491 if ( mi==ma ) return false;
00492 minmax=std::make_pair ( mi,ma );
00493 return true;
00494 }
00495 return false;
00496 }
00497
00498 inline const std::string& Config::getFilename() const
00499 {
00500 return m_fileName;
00501 }
00502
00503 #endif