00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <fstream>
00031 #include <sstream>
00032
00033 #include "rviz/config.h"
00034 #include "rviz/uniform_string_stream.h"
00035
00036 namespace rviz
00037 {
00038
00039 bool Config::readFromFile( const std::string& filename )
00040 {
00041 std::ifstream in( filename.c_str() );
00042 if( in )
00043 {
00044 read( in );
00045 return true;
00046 }
00047 else
00048 {
00049 std::cerr << "Config file '" << filename << "' could not be opened for reading." << std::endl;
00050 return false;
00051 }
00052 }
00053
00054 bool Config::writeToFile( const std::string& filename )
00055 {
00056 std::ofstream out( filename.c_str() );
00057 if( out )
00058 {
00059 write( out );
00060 return true;
00061 }
00062 else
00063 {
00064 std::cerr << "Config file '" << filename << "' could not be opened for writing." << std::endl;
00065 return false;
00066 }
00067 }
00068
00069 void Config::read( std::istream& input )
00070 {
00071 size_t equals_sign_index;
00072 std::string line;
00073 std::string current_dir;
00074 std::string key, value;
00075
00076
00077 while( !input.eof() && !input.fail() )
00078 {
00079
00080 line.clear();
00081 std::getline( input, line );
00082
00083 if( line.size() > 0 )
00084 {
00085 if( line[0] == '[' )
00086 {
00087 current_dir = line.substr( 1, line.size() - 2 );
00088 }
00089 else
00090 {
00091
00092 equals_sign_index = line.find_first_of( '=' );
00093 key = line.substr( 0, equals_sign_index );
00094 key = unescapeKey( key );
00095 value = line.substr( equals_sign_index + 1 );
00096
00097
00098 if( key.size() > 0 )
00099 {
00100 if( current_dir.size() > 0 )
00101 {
00102 key = current_dir + '/' + key;
00103 }
00104 set( key, value );
00105 }
00106 }
00107 }
00108 }
00109 }
00110
00111 void Config::write( std::ostream& output )
00112 {
00113 std::string last_prefix;
00114 std::string key_tail;
00115 std::string key_prefix;
00116
00117 for( Iterator it = begin(); it != end(); it++ )
00118 {
00119 const std::string& key = (*it).first;
00120 const std::string& value = (*it).second;
00121 size_t last_slash_index = key.find_last_of( '/' );
00122 if( last_slash_index == std::string::npos )
00123 {
00124 key_tail = key;
00125 key_prefix = "";
00126 }
00127 else
00128 {
00129 key_tail = key.substr( last_slash_index + 1 );
00130 key_prefix = key.substr( 0, last_slash_index );
00131 }
00132 if( key_prefix != last_prefix )
00133 {
00134 writeDirectory( output, key_prefix, last_prefix );
00135 }
00136 key_tail = escapeKey( key_tail );
00137 output << key_tail << "=" << value << std::endl;
00138 last_prefix = key_prefix;
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 void Config::writeDirectory( std::ostream& output, const std::string& new_dir, const std::string& prev_dir )
00167 {
00168
00169 size_t min_size = new_dir.size() < prev_dir.size() ? new_dir.size() : prev_dir.size();
00170
00171 size_t index = 0;
00172 for( ; index < min_size; index++ )
00173 {
00174 if( new_dir[ index ] != prev_dir[ index ] )
00175 {
00176 break;
00177 }
00178 }
00179
00180
00181 if( index < new_dir.size() && new_dir[ index ] == '/' )
00182 {
00183 index++;
00184 }
00185
00186
00187
00188 bool done = false;
00189 while( !done )
00190 {
00191 index = new_dir.find_first_of( '/', index );
00192 if( index == std::string::npos )
00193 {
00194 index = new_dir.size();
00195 done = true;
00196 }
00197 output << '[' << new_dir.substr( 0, index ) << ']' << std::endl;
00198 index++;
00199 }
00200 }
00201
00202 std::string Config::escapeKey( const std::string& raw_key )
00203 {
00204 std::istringstream in( raw_key );
00205 std::ostringstream out;
00206 char c;
00207 while( in.good() )
00208 {
00209 c = in.get();
00210 if( in )
00211 {
00212 switch( c )
00213 {
00214 case ':':
00215 case ' ':
00216 case '\\':
00217 out << '\\';
00218 }
00219 out << c;
00220 }
00221 }
00222 return out.str();
00223 }
00224
00225 std::string Config::unescapeKey( const std::string& cooked_key )
00226 {
00227 std::istringstream in( cooked_key );
00228 std::ostringstream out;
00229 char c;
00230 while( in.good() )
00231 {
00232 c = in.get();
00233 if( in.good() )
00234 {
00235 if( c == '\\' )
00236 {
00237 c = in.get();
00238 if( in.good() )
00239 {
00240 out << c;
00241 }
00242 }
00243 else
00244 {
00245 out << c;
00246 }
00247 }
00248 }
00249 return out.str();
00250 }
00251
00252 void Config::set( const std::string& key, const std::string& value )
00253 {
00254 map_[ stripFirstSlash( key )] = value;
00255 }
00256
00257 void Config::set( const std::string& key, float value )
00258 {
00259 UniformStringStream ss;
00260 ss << value;
00261 map_[ stripFirstSlash( key )] = ss.str();
00262 }
00263
00264 void Config::set( const std::string& key, int value )
00265 {
00266 UniformStringStream ss;
00267 ss << value;
00268 map_[ stripFirstSlash( key )] = ss.str();
00269 }
00270
00271 bool Config::get( const std::string& key, std::string* output, const std::string& default_value )
00272 {
00273 Iterator it = map_.find( stripFirstSlash( key ));
00274 if( it != map_.end() )
00275 {
00276 *output = (*it).second;
00277 return true;
00278 }
00279 *output = default_value;
00280 return false;
00281 }
00282
00283 bool Config::get( const std::string& key, float* output, float default_value )
00284 {
00285 Iterator it = map_.find( stripFirstSlash( key ));
00286 if( it != map_.end() )
00287 {
00288 UniformStringStream ss;
00289 ss.str( (*it).second );
00290 ss.parseFloat( *output );
00291 if( !ss.fail() )
00292 {
00293 return true;
00294 }
00295 }
00296 *output = default_value;
00297 return false;
00298 }
00299
00300 bool Config::get( const std::string& key, int* output, int default_value )
00301 {
00302 Iterator it = map_.find( stripFirstSlash( key ));
00303 if( it != map_.end() )
00304 {
00305 UniformStringStream ss;
00306 ss.str( (*it).second );
00307 ss >> *output;
00308 if( !ss.fail() )
00309 {
00310 return true;
00311 }
00312 }
00313 *output = default_value;
00314 return false;
00315 }
00316
00317 const std::string Config::stripFirstSlash( const std::string& str )
00318 {
00319 if( str[0] == '/' )
00320 {
00321 return str.substr( 1 );
00322 }
00323 else
00324 {
00325 return str;
00326 }
00327 }
00328
00329 bool Config::DirectoryCompare::operator() (const std::string& lhs, const std::string& rhs) const
00330 {
00331 int start = 0;
00332 int count;
00333 int rhs_count;
00334 size_t l_slash_index, r_slash_index;
00335 bool l_on_last, r_on_last;
00336
00337
00338
00339
00340
00341 while( true )
00342 {
00343
00344 l_slash_index = lhs.find_first_of( '/', start );
00345 r_slash_index = rhs.find_first_of( '/', start );
00346 l_on_last = ( l_slash_index == std::string::npos );
00347 if( l_on_last )
00348 {
00349 l_slash_index = lhs.size();
00350 }
00351 r_on_last = ( r_slash_index == std::string::npos );
00352 if( r_on_last )
00353 {
00354 r_slash_index = rhs.size();
00355 }
00356
00357
00358
00359
00360
00361 if( !l_on_last && r_on_last )
00362 {
00363 return false;
00364 }
00365 if( l_on_last && !r_on_last )
00366 {
00367 return true;
00368 }
00369
00370
00371 count = l_slash_index - start;
00372 rhs_count = r_slash_index - start;
00373
00374
00375 int result = lhs.compare( start, count, rhs, start, rhs_count );
00376
00377
00378
00379 if( result != 0 )
00380 {
00381 return result < 0;
00382 }
00383
00384
00385
00386 if( start + rhs_count >= (int)rhs.size() )
00387 {
00388 return false;
00389 }
00390
00391
00392
00393 start += count + 1;
00394
00395
00396
00397 if( start > (int)lhs.size() )
00398 {
00399 return true;
00400 }
00401 }
00402 }
00403
00404 }