MRXT: The Multi-Robot eXploration Tool
Multi-Robot autonomous exploration and mapping simulator.
|
00001 // ConfigFile.cpp 00002 00003 #include "ConfigFile.h" 00004 00005 using std::string; 00006 00007 ConfigFile::ConfigFile( string filename, string delimiter, 00008 string comment, string sentry ) 00009 : myDelimiter(delimiter), myComment(comment), mySentry(sentry) 00010 { 00011 // Construct a ConfigFile, getting keys and values from given file 00012 00013 std::ifstream in( filename.c_str() ); 00014 00015 if( !in ) throw file_not_found( filename ); 00016 00017 in >> (*this); 00018 } 00019 00020 00021 ConfigFile::ConfigFile() 00022 : myDelimiter( string(1,'=') ), myComment( string(1,'#') ) 00023 { 00024 // Construct a ConfigFile without a file; empty 00025 } 00026 00027 00028 void ConfigFile::remove( const string& key ) 00029 { 00030 // Remove key and its value 00031 myContents.erase( myContents.find( key ) ); 00032 return; 00033 } 00034 00035 00036 bool ConfigFile::keyExists( const string& key ) const 00037 { 00038 // Indicate whether key is found 00039 mapci p = myContents.find( key ); 00040 return ( p != myContents.end() ); 00041 } 00042 00043 00044 /* static */ 00045 void ConfigFile::trim( string& s ) 00046 { 00047 // Remove leading and trailing whitespace 00048 static const char whitespace[] = " \n\t\v\r\f"; 00049 s.erase( 0, s.find_first_not_of(whitespace) ); 00050 s.erase( s.find_last_not_of(whitespace) + 1U ); 00051 } 00052 00053 00054 std::ostream& operator<<( std::ostream& os, const ConfigFile& cf ) 00055 { 00056 // Save a ConfigFile to os 00057 for( ConfigFile::mapci p = cf.myContents.begin(); 00058 p != cf.myContents.end(); 00059 ++p ) 00060 { 00061 os << p->first << " " << cf.myDelimiter << " "; 00062 os << p->second << std::endl; 00063 } 00064 return os; 00065 } 00066 00067 00068 std::istream& operator>>( std::istream& is, ConfigFile& cf ) 00069 { 00070 // Load a ConfigFile from is 00071 // Read in keys and values, keeping internal whitespace 00072 typedef string::size_type pos; 00073 const string& delim = cf.myDelimiter; // separator 00074 const string& comm = cf.myComment; // comment 00075 const string& sentry = cf.mySentry; // end of file sentry 00076 const pos skip = delim.length(); // length of separator 00077 00078 string nextline = ""; // might need to read ahead to see where value ends 00079 00080 while( is || nextline.length() > 0 ) 00081 { 00082 // Read an entire line at a time 00083 string line; 00084 if( nextline.length() > 0 ) 00085 { 00086 line = nextline; // we read ahead; use it now 00087 nextline = ""; 00088 } 00089 else 00090 { 00091 std::getline( is, line ); 00092 } 00093 00094 // Ignore comments 00095 line = line.substr( 0, line.find(comm) ); 00096 00097 // Check for end of file sentry 00098 if( sentry != "" && line.find(sentry) != string::npos ) return is; 00099 00100 // Parse the line if it contains a delimiter 00101 pos delimPos = line.find( delim ); 00102 if( delimPos < string::npos ) 00103 { 00104 // Extract the key 00105 string key = line.substr( 0, delimPos ); 00106 line.replace( 0, delimPos+skip, "" ); 00107 00108 // See if value continues on the next line 00109 // Stop at blank line, next line with a key, end of stream, 00110 // or end of file sentry 00111 bool terminate = false; 00112 while( !terminate && is ) 00113 { 00114 std::getline( is, nextline ); 00115 terminate = true; 00116 00117 string nlcopy = nextline; 00118 ConfigFile::trim(nlcopy); 00119 if( nlcopy == "" ) continue; 00120 00121 nextline = nextline.substr( 0, nextline.find(comm) ); 00122 if( nextline.find(delim) != string::npos ) 00123 continue; 00124 if( sentry != "" && nextline.find(sentry) != string::npos ) 00125 continue; 00126 00127 nlcopy = nextline; 00128 ConfigFile::trim(nlcopy); 00129 if( nlcopy != "" ) line += "\n"; 00130 line += nextline; 00131 terminate = false; 00132 } 00133 00134 // Store key and value 00135 ConfigFile::trim(key); 00136 ConfigFile::trim(line); 00137 cf.myContents[key] = line; // overwrites if key is repeated 00138 } 00139 } 00140 00141 return is; 00142 }