//This file is part of Photon (http://photon.sourceforge.net) //Copyright (C) 2004-2005 James Turk // // Author: // James Turk (jpt2433@rit.edu) // // Version: // $Id: ConfigFile.h,v 1.3 2005/02/03 20:38:56 cozman Exp $ // // Revisions: // $Log: ConfigFile.h,v $ // Revision 1.3 2005/02/03 20:38:56 cozman // conversion to LF // // Revision 1.2 2005/01/31 15:44:13 cozman // ConfigFile rewrite // // Revision 1.1 2005/01/27 03:35:23 cozman // initial import (exceptions,types, and logging,oh my!) // // #ifndef PHOTON_UTIL_CONFIGFILE_H #define PHOTON_UTIL_CONFIGFILE_H #include #include #include #include #include namespace photon { namespace util { // Class: ConfigFile // ConfigFile class, for reading/writing INI-style config files. // // File format is fairly flexible, whitespace and comments beginning with # or // ; are ignored & left intact. // // Use []'s to denote sections. // // Variables are defined in var=val format. class ConfigFile { public: // types used in ConfigFile //predicate for search template class StrPairEq { public: typedef pairT first_argument_type; typedef std::string second_argument_type; typedef bool result_type; bool operator()(const pairT& lhs, const std::string& rhs) const; }; typedef std::pair Variable; typedef std::list< Variable > Section; typedef std::pair< std::string, std::list< Variable > > NamedSection; typedef std::list< NamedSection > Layout; // Group: (Con/De)structors public: // Function: ConfigFile // Default constructor for ConfigFile. ConfigFile(); // Function: ConfigFile // Constructor for ConfigFile, calls . // // Parameters: // filename - Name of ConfigFile to open. ConfigFile(const std::string& filename); // Function: ~ConfigFile // Calls close upon the ConfigFile. virtual ~ConfigFile(); // Group: File Access public: // Function: open // open a file, processing it as an INI-like config file. // // Parameters: // filename - Name of ConfigFile to open. void open(const std::string& filename); // Function: flush // Flushes the data written to the config file to disk, generally needs // not be called. void flush(); // Function: close // Flushes the data and closes, open must be called again before using same // ConfigFile. void close(); // Function: setVariable // Template function for setting variables in the config file. // // WARNING: Do not try to use this with user-defined types, numeric types // and strings work fine, and this is all that should be contained in // an INI. // // Parameters: // sec - section name within config file // var - variable name within section // value - value to set variable equal to template void setVariable(const std::string& sec, const std::string& var, varType value); // Function: getVariable // Template function for getting values from the config file. Supports // returning a default value if the desired variable was not found. // // WARNING: Do not try to use this with user-defined types, numeric types // and strings work fine, and this is all that should be contained in // an INI. // // Parameters: // sec - section name within config file // var - variable name within section // defVal - value to return if variable does not exist // // Returns: // Value of variable within config file or defVal if value was not found. template varType getVariable(const std::string& sec, const std::string& var, varType defVal) const; private: static std::string cleanString(const std::string& str); static std::string bracketString(const std::string& str); private: Layout layout_; std::string filename_; }; //predicate for search template bool ConfigFile::StrPairEq::operator()(const pairT& lhs, const std::string& rhs) const { return ConfigFile::cleanString(lhs.first) == ConfigFile::cleanString(rhs); } //Template implementation template void ConfigFile::setVariable(const std::string& sec, const std::string& var, varType value) { std::string secBrac(bracketString(sec)); Layout::iterator secIter; Section::iterator varIter; std::ostringstream ss; ss << value; //write value to string //search for section secIter = std::find_if( layout_.begin(), layout_.end(), std::bind2nd(StrPairEq(), secBrac) ); // add the section if it does not exist if(secIter == layout_.end()) { layout_.push_back( NamedSection( secBrac, Section() ) ); //search again, assert that it now exists secIter = std::find_if( layout_.begin(), layout_.end(), std::bind2nd(StrPairEq(), secBrac) ); assert(secIter != layout_.end()); } //search for variable varIter = std::find_if( secIter->second.begin(), secIter->second.end(), std::bind2nd(StrPairEq(), var) ); // add the variable if it does not exist if(varIter == secIter->second.end()) { secIter->second.push_back( Variable(var, ss.str()) ); } else { varIter->second = ss.str(); } } //template specialization for setVariable /*template<> void ConfigFile::setVariable(std::string sec, std::string var, std::string value) { sec = "[" + sec + "]"; //add []s to section name value = "\"" + value + "\""; //add ""s to value layout_[sec][var] = value; //actually set it }*/ template varType ConfigFile::getVariable(const std::string& sec, const std::string& var, varType defVal) const { std::string secBrac(bracketString(sec)); std::stringstream ss; varType ret(defVal); Layout::const_iterator secIter; Section::const_iterator varIter; secIter = std::find_if( layout_.begin(), layout_.end(), std::bind2nd(StrPairEq(), secBrac) ); if(secIter != layout_.end()) { varIter = std::find_if( secIter->second.begin(), secIter->second.end(), std::bind2nd(StrPairEq(), var) ); if(varIter != secIter->second.end()) { ss.str(varIter->second); ss >> ret; } } return ret; } } } #endif //PHOTON_UTIL_CONFIGFILE_H