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