00001 #include "SdlArs.h"
00002
00003 #include <fstream>
00004 #include <iterator>
00005
00006 namespace Cfg
00007 {
00008 static deque<Handler *> CfgStacks;
00009
00010 const bool Empty( void )
00011 {
00012 return CfgStacks.empty();
00013 }
00014
00015 void Push( Handler *aCfg )
00016 {
00017 CfgStacks.push_back( aCfg );
00018 }
00019
00020 Handler &Push( string aFile )
00021 {
00022 if( aFile[0] == '@' )
00023 aFile = GetCfg().GetCfgFile( "Paths" , aFile.substr( 1 ) );
00024
00025 Push( new Handler( aFile ) );
00026 return *CfgStacks.back();
00027 }
00028
00029 void Pop( const Handler &aCfg )
00030 {
00031 deque<Handler *>::iterator pos = find_if( CfgStacks.begin() , CfgStacks.end() , bind2nd( mem_fun( &Handler::IsTheFile ) , aCfg.GetFilename().c_str() ) );
00032 if( pos != CfgStacks.end() )
00033 {
00034 delete *pos;
00035 CfgStacks.erase( pos );
00036 }
00037 }
00038
00039 void Pop( void )
00040 {
00041 if( !Empty() )
00042 delete CfgStacks.back();
00043 CfgStacks.pop_back();
00044 }
00045
00046 Handler &GetCfg( string aFile )
00047 {
00048 if( aFile[0] == '@' )
00049 aFile = GetCfg().GetCfgFile( "Paths" , aFile.substr( 1 ) );
00050
00051 deque<Handler *>::iterator pos = find_if( CfgStacks.begin() , CfgStacks.end() , bind2nd( mem_fun( &Handler::IsTheFile ) , aFile.c_str() ) );
00052
00053 if( pos == CfgStacks.end() )
00054 return Push( aFile );
00055 return **pos;
00056 }
00057
00059 Handler::Handler( const string &aFile )
00060 : CfgFile( aFile ) , dirty( false ) , cnt( 0 )
00061 {
00062 string::size_type n = CfgFile.rfind( '\\' );
00063 if( n == string::npos )
00064 n = CfgFile.rfind( '/' );
00065 if( n == string::npos )
00066 cfgPath = "./";
00067 else
00068 cfgPath = CfgFile.substr( 0 , n + 1 );
00069
00070 ifstream ifd( CfgFile.c_str() );
00071
00072 vector<string> e;
00073 vList.insert( make_pair( icstring( "" ) , e ) );
00074 map<icstring, vector<string> >::iterator pos = vList.find( "" );
00075
00076 while( !ifd.fail() )
00077 {
00078 char buffer[4096] = "";
00079 ifd.getline( buffer , sizeof buffer );
00080 pos = AddLine( pos , buffer );
00081 if( ifd.eof() )
00082 break;
00083
00084 }
00085 }
00086
00087 Handler::~Handler( void )
00088 {
00089 for( map<icstring , vector<string> >::iterator it = vList.begin() ; it != vList.end() ; ++it )
00090 it->second.clear();
00091 vList.clear();
00092 }
00093
00094 map<icstring, vector<string> >::iterator Handler::AddLine( map<icstring, vector<string> >::iterator pos , const string &aline )
00095 {
00096
00097
00098 if( aline[0] == '[' )
00099 {
00100 string::size_type at = aline.find( ']' );
00101 if( at != string::npos )
00102 {
00103 icstring ics = aline.substr( 1 , at - 1 ).c_str();
00104 map<icstring, vector<string> >::iterator pos2 = vList.find( ics );
00105 if( pos2 == vList.end() )
00106 {
00107 vector<string> e;
00108 icstring ics = aline.substr( 1 , at - 1 ).c_str();
00109 return vList.insert( make_pair( ics , e ) ).first;
00110 }
00111 return pos2;
00112 }
00113 }
00114
00115
00116 if( aline.find( "=" ) != string::npos && aline[0] != '#' && aline.substr( 0 , 2 ) != "//" )
00117 {
00118 icstring tmp = aline.substr( 0 , aline.find( '=' ) ).c_str();
00119 icstring s = Ars::strip( tmp );
00120 for( vector<string>::iterator at = pos->second.begin() ; at != pos->second.end() ; ++at )
00121 {
00122 tmp = at->substr( 0 , at->find( '=' ) ).c_str();
00123 icstring ics = Ars::strip( tmp );
00124 if( s == ics )
00125 {
00126 *at = aline;
00127 return pos;
00128 }
00129 }
00130 cnt += 1;
00131 }
00132
00133 pos->second.push_back( aline );
00134 return pos;
00135 }
00136
00137 void Handler::SetData( const string &aData )
00138 {
00139 dirty = false;
00140 vList.clear();
00141 string::size_type n0 = 0 , n1 = aData.find( "\n" , n0 );
00142 cnt = 0;
00143
00144 vector<string> e;
00145 vList.insert( make_pair( icstring( "" ) , e ) );
00146 map<icstring, vector<string> >::iterator pos = vList.find( "" );
00147
00148 while( n1 != string::npos )
00149 {
00150 pos = AddLine( pos , string( aData.substr( n0 , n1 - n0 ) ) );
00151 n0 = n1 + 1;
00152 n1 = aData.find( "\n" , n0 );
00153 }
00154 }
00155
00156 void Handler::Flush( const string &aFilename )
00157 {
00158 if( !aFilename.empty() || dirty )
00159 {
00160 ofstream of( (aFilename.empty() ? CfgFile.c_str() : aFilename.c_str()) , ios::out );
00161 for( map<icstring,vector<string> >::iterator it = vList.begin() ; it != vList.end() ; ++it )
00162 {
00163 if( !it->first.empty() )
00164 of << "[" << it->first.c_str() << "]" << endl;
00165 copy( it->second.begin() , it->second.end() , ostream_iterator<string>( of , "\n" ) );
00166 }
00167 }
00168 dirty = false;
00169 }
00170
00171 string Handler::GetCdr( const icstring &aSection , const string &aId )
00172 {
00173 map<icstring, vector<string> >::iterator pos = vList.find( aSection );
00174 if( pos != vList.end() )
00175 {
00176 for( vector<string>::iterator at = pos->second.begin() ; at != pos->second.end() ; ++at )
00177 {
00178 string::size_type n;
00179 if( (n = at->find( '=' )) != string::npos )
00180 {
00181 icstring tmp = at->substr( 0 , n ).c_str();
00182 icstring ics = Ars::strip( tmp );
00183 if( ics == icstring( aId.c_str() ) )
00184 return at->substr( at->find_first_not_of( ' ' , n + 1 ) );
00185
00186 }
00187 }
00188 }
00189 return string( "" );
00190 }
00191
00192 int Handler::GetCfgInt( const string &aSection , const string &aId , const int aDefaultValue )
00193 {
00194 string s = GetCdr( icstring( aSection.c_str() ) , aId );
00195
00196 int val = aDefaultValue;
00197 if( s.substr( 0 , 2 ) == "0x" || s.substr( 0 , 2 ) == "0X" )
00198 sscanf( s.substr( 2 ).c_str() , "%x" , &val );
00199 else if( !s.empty() )
00200 sscanf( s.c_str() , "%d" , &val );
00201
00202 return val;
00203 }
00204
00205 int Handler::GetCfgHex( const string &aSection , const string &aId , const int aDefaultValue )
00206 {
00207 string s = GetCdr( icstring( aSection.c_str() ) , aId );
00208
00209 int val = aDefaultValue;
00210 if( !s.empty() )
00211 sscanf( s.c_str() , "%x" , &val );
00212
00213 return val;
00214 }
00215
00216 Ars::RGBColor Handler::GetCfgColorHex( const string &aSection , const string &aId , const Ars::RGBColor col )
00217 {
00218 unsigned long int c = GetCfgInt( aSection , aId , (col.red << 16) + (col.green << 8) + col.blue + (col.alpha << 24) );
00219 return Ars::RGBColor( (unsigned char)( (c >> 16) & 0xff ) , (unsigned char)( (c >> 8) & 0xff ) , (unsigned char)( c & 0xff ) , (unsigned char)( c & 0xff000000 ? (c >> 24) & 0xff : 0xff ) );
00220 }
00221
00222 double Handler::GetCfgDbl( const string &aSection , const string &aId , const double aDefaultValue )
00223 {
00224 string s = GetCdr( icstring( aSection.c_str() ) , aId );
00225
00226 double val = aDefaultValue;
00227 if( !s.empty() )
00228 sscanf( s.c_str() , "%lf" , &val );
00229
00230 return val;
00231 }
00232
00233 vector<double> &Handler::GetCfgDbl( const string &aSection , const string &aId , vector<double> &ans )
00234 {
00235 string s = GetCdr( icstring( aSection.c_str() ) , aId );
00236
00237 while( !s.empty() )
00238 {
00239 double val = 0.0;
00240 sscanf( s.c_str() , "%lf" , &val );
00241 ans.push_back( val );
00242 size_t n = s.find_first_of( " \t\n" );
00243 if( n != string::npos )
00244 if( (n = s.find_first_not_of( " \t\n" , n )) != string::npos )
00245 s = s.substr( n );
00246 else
00247 break;
00248 else
00249 break;
00250 }
00251 return ans;
00252 }
00253
00254 string Handler::GetCfgString( const string &aSection , const string &aId , const string &aDefaultValue )
00255 {
00256 string s = GetCdr( icstring( aSection.c_str() ) , aId );
00257
00258 return (s.empty() ? aDefaultValue : s);
00259 }
00260
00261 string Handler::GetCfgFile( const string &aSection , const string &aId , const string &aDefaultValue )
00262 {
00263 string s = GetCdr( icstring( aSection.c_str() ) , aId );
00264
00265 return (s.empty() ? aDefaultValue : (cfgPath + s));
00266 }
00267
00268 void Handler::SetCfgInt( const string &aSection ,const string &aId , const int aValue )
00269 {
00270 dirty = true;
00271 char buffer[4096];
00272 sprintf( buffer , " = %d" , aValue );
00273 AddLine( AddLine( vList.begin() , string( "[" ) + aSection + "]" ) , aId + buffer );
00274 }
00275
00276 void Handler::SetCfgHex( const string &aSection ,const string &aId , const int aValue )
00277 {
00278 dirty = true;
00279 char buffer[4096];
00280 sprintf( buffer , " = 0x%08x" , aValue );
00281 AddLine( AddLine( vList.begin() , string( "[" ) + aSection + "]" ) , aId + buffer );
00282 }
00283
00284 void Handler::SetCfgDbl( const string &aSection ,const string &aId , const double aValue )
00285 {
00286 dirty = true;
00287 char buffer[4096];
00288 sprintf( buffer , " = %f" , aValue );
00289 AddLine( AddLine( vList.begin() , string( "[" ) + aSection + "]" ) , aId + buffer );
00290 }
00291
00292 void Handler::SetCfgString( const string &aSection ,const string &aId , const string &aValue )
00293 {
00294 dirty = true;
00295 AddLine( AddLine( vList.begin() , string( "[" ) + aSection + "]" ) , string( aId + " = " ) + aValue );
00296 }
00297
00298 void Handler::SetCfgFile( const string &aSection ,const string &aId , const string &aValue )
00299 {
00300 string v = aValue;
00301 string::size_type n = v.find( cfgPath );
00302 if( n != string::npos )
00303 v = v.substr( n + cfgPath.length() );
00304 dirty = true;
00305 AddLine( AddLine( vList.begin() , string( "[" ) + aSection + "]" ) , string( aId + " = " ) + v );
00306 }
00307
00308 void Handler::SetCfgColorHex( const string &aSection , const string &aId , const Ars::RGBColor c )
00309 {
00310 dirty = true;
00311 char buffer[4096];
00312 sprintf( buffer , " = 0x%02x%02x%02x%02x" , c.alpha , c.red , c.green , c.blue );
00313 AddLine( AddLine( vList.begin() , string( "[" ) + aSection + "]" ) , aId + buffer );
00314 }
00315
00316 }
00317