PageRenderTime 35ms CodeModel.GetById 19ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 1ms

/xbmc/visualizations/XBMCProjectM/libprojectM/ConfigFile.cpp

http://github.com/xbmc/xbmc
C++ | 142 lines | 94 code | 29 blank | 19 comment | 22 complexity | efd67b25a2b2542b64796fd3f87309b2 MD5 | raw file
  1// ConfigFile.cpp
  2
  3#include "ConfigFile.h"
  4
  5using std::string;
  6
  7ConfigFile::ConfigFile( string filename, string delimiter,
  8                        string comment, string sentry )
  9	: myDelimiter(delimiter), myComment(comment), mySentry(sentry)
 10{
 11	// Construct a ConfigFile, getting keys and values from given file
 12	
 13	std::ifstream in( filename.c_str() );
 14	
 15	if( !in ) throw file_not_found( filename ); 
 16	
 17	in >> (*this);
 18}
 19
 20
 21ConfigFile::ConfigFile()
 22	: myDelimiter( string(1,'=') ), myComment( string(1,'#') )
 23{
 24	// Construct a ConfigFile without a file; empty
 25}
 26
 27
 28void ConfigFile::remove( const string& key )
 29{
 30	// Remove key and its value
 31	myContents.erase( myContents.find( key ) );
 32	return;
 33}
 34
 35
 36bool ConfigFile::keyExists( const string& key ) const
 37{
 38	// Indicate whether key is found
 39	mapci p = myContents.find( key );
 40	return ( p != myContents.end() );
 41}
 42
 43
 44/* static */
 45void ConfigFile::trim( string& s )
 46{
 47	// Remove leading and trailing whitespace
 48	static const char whitespace[] = " \n\t\v\r\f";
 49	s.erase( 0, s.find_first_not_of(whitespace) );
 50	s.erase( s.find_last_not_of(whitespace) + 1U );
 51}
 52
 53
 54std::ostream& operator<<( std::ostream& os, const ConfigFile& cf )
 55{
 56	// Save a ConfigFile to os
 57	for( ConfigFile::mapci p = cf.myContents.begin();
 58	     p != cf.myContents.end();
 59		 ++p )
 60	{
 61		os << p->first << " " << cf.myDelimiter << " ";
 62		os << p->second << std::endl;
 63	}
 64	return os;
 65}
 66
 67
 68std::istream& operator>>( std::istream& is, ConfigFile& cf )
 69{
 70	// Load a ConfigFile from is
 71	// Read in keys and values, keeping internal whitespace
 72	typedef string::size_type pos;
 73	const string& delim  = cf.myDelimiter;  // separator
 74	const string& comm   = cf.myComment;    // comment
 75	const string& sentry = cf.mySentry;     // end of file sentry
 76	const pos skip = delim.length();        // length of separator
 77	
 78	string nextline = "";  // might need to read ahead to see where value ends
 79	
 80	while( is || nextline.length() > 0 )
 81	{
 82		// Read an entire line at a time
 83		string line;
 84		if( nextline.length() > 0 )
 85		{
 86			line = nextline;  // we read ahead; use it now
 87			nextline = "";
 88		}
 89		else
 90		{
 91			std::getline( is, line );
 92		}
 93		
 94		// Ignore comments
 95		line = line.substr( 0, line.find(comm) );
 96		
 97		// Check for end of file sentry
 98		if( sentry != "" && line.find(sentry) != string::npos ) return is;
 99		
100		// Parse the line if it contains a delimiter
101		pos delimPos = line.find( delim );
102		if( delimPos < string::npos )
103		{
104			// Extract the key
105			string key = line.substr( 0, delimPos );
106			line.replace( 0, delimPos+skip, "" );
107			
108			// See if value continues on the next line
109			// Stop at blank line, next line with a key, end of stream,
110			// or end of file sentry
111			bool terminate = false;
112			while( !terminate && is )
113			{
114				std::getline( is, nextline );
115				terminate = true;
116				
117				string nlcopy = nextline;
118				ConfigFile::trim(nlcopy);
119				if( nlcopy == "" ) continue;
120				
121				nextline = nextline.substr( 0, nextline.find(comm) );
122				if( nextline.find(delim) != string::npos )
123					continue;
124				if( sentry != "" && nextline.find(sentry) != string::npos )
125					continue;
126				
127				nlcopy = nextline;
128				ConfigFile::trim(nlcopy);
129				if( nlcopy != "" ) line += "\n";
130				line += nextline;
131				terminate = false;
132			}
133			
134			// Store key and value
135			ConfigFile::trim(key);
136			ConfigFile::trim(line);
137			cf.myContents[key] = line;  // overwrites if key is repeated
138		}
139	}
140	
141	return is;
142}