• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

/Users/jmonk/Physics/ForIA/src/ConfigurationFile.cxx

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

Generated on Mon Jul 30 2012 16:56:35 for ForIA by  doxygen 1.7.2