| René Nyffenegger's collection of things on the web | |
|
René Nyffenegger on Oracle - Most wanted - Feedback
|
A C++ Class to read Configuration Files | ||
|
This class uses the class Chameleon. Chameleon is a string to/from double conversion class.
Here's ConfigFile.h
ConfigFile.h
#ifndef __CONFIG_FILE_H__
#define __CONFIG_FILE_H__
#include <string>
#include <map>
#include "Chameleon.h"
class ConfigFile {
std::map<std::string,Chameleon> content_;
public:
ConfigFile(std::string const& configFile);
Chameleon const& Value(std::string const& section, std::string const& entry) const;
Chameleon const& Value(std::string const& section, std::string const& entry, double value);
Chameleon const& Value(std::string const& section, std::string const& entry, std::string const& value);
};
#endif
Here's ConfigFile.cpp
ConfigFile.cpp
#include "ConfigFile.h"
#include <fstream>
std::string trim(std::string const& source, char const* delims = " \t\r\n") {
std::string result(source);
std::string::size_type index = result.find_last_not_of(delims);
if(index != std::string::npos)
result.erase(++index);
index = result.find_first_not_of(delims);
if(index != std::string::npos)
result.erase(0, index);
else
result.erase();
return result;
}
ConfigFile::ConfigFile(std::string const& configFile) {
std::ifstream file(configFile.c_str());
std::string line;
std::string name;
std::string value;
std::string inSection;
int posEqual;
while (std::getline(file,line)) {
if (! line.length()) continue;
if (line[0] == '#') continue;
if (line[0] == ';') continue;
if (line[0] == '[') {
inSection=trim(line.substr(1,line.find(']')-1));
continue;
}
posEqual=line.find('=');
name = trim(line.substr(0,posEqual));
value = trim(line.substr(posEqual+1));
content_[inSection+'/'+name]=Chameleon(value);
}
}
Chameleon const& ConfigFile::Value(std::string const& section, std::string const& entry) const {
std::map<std::string,Chameleon>::const_iterator ci = content_.find(section + '/' + entry);
if (ci == content_.end()) throw "does not exist";
return ci->second;
}
Chameleon const& ConfigFile::Value(std::string const& section, std::string const& entry, double value) {
try {
return Value(section, entry);
} catch(const char *) {
return content_.insert(std::make_pair(section+'/'+entry, Chameleon(value))).first->second;
}
}
Chameleon const& ConfigFile::Value(std::string const& section, std::string const& entry, std::string const& value) {
try {
return Value(section, entry);
} catch(const char *) {
return content_.insert(std::make_pair(section+'/'+entry, Chameleon(value))).first->second;
}
}
A test program
ConfigFileTest.cpp
ConfigFileTest.cpp
#include "ConfigFile.h"
#include <iostream>
int main() {
ConfigFile cf("config.txt");
std::string foo;
std::string water;
double four;
foo = cf.Value("section_1","foo" );
water = cf.Value("section_2","water");
four = cf.Value("section_2","four" );
std::cout << foo << std::endl;
std::cout << water << std::endl;
std::cout << four << std::endl;
return 0;
}
Here's the configuration file that's being read by the test program:
config.txt
[section_1] foo = bar water= h2o [section_2] foo = foo water= wet four = 4.2
Compiling the test program with n:
g++ -Wall Chameleon.cpp ConfigFile.cpp ConfigFileTest.cpp -o ConfigFileTest.exe Thanks
My special thanks go to Dieter Vrancken who improved this class, see also this entry in my blog.
Thanks also to Lars Schouw who pointed out an error on this page and Christian Decker who spotted an error in the code.
|