全部博文(41)
分类: C/C++
2009-09-19 17:55:01
#pragma once
#include <string>
#include <map>
#include <boost/lexical_cast.hpp>
/*
INI配置文件解析,几点说明
1. 支持以'#'或';'开头的行注释,不支持右注释
2. 系统默认有一个空域[],INI文件中的项如果没没有指定域就用它
3. 取配置值时指定域和键,若没有指定域则到默认域中查找
4. 键值允许空格,'='两边允许空格和制表位
*/
class IniConfig
{
public:
explicit IniConfig(const char* iniFile);
// 通过域和键来获取配置值
template <typename T>
T get(const std::string& section, const std::string& key)
{
check(section, key);
return boost::lexical_cast<T>(configs_[section][key]);
}
const std::string& get(const std::string& section, const std::string& key)
{
check(section, key);
return configs_[section][key];
}
// 获取默认域的键值
template <typename T>
T get(const std::string& key)
{
check("", key);
return boost::lexical_cast<T>(configs_[""][key]);
}
const std::string& get(const std::string& key)
{
check("", key);
return configs_[""][key];
}
// 修改配置项
void set(const std::string& section, const std::string& key, const std::string& newValue)
{
check(section, key);
configs_[section][key] = newValue;
}
private:
IniConfig(const IniConfig&);
IniConfig& operator=(const IniConfig&);
// 解析一行
void parse_line(std::string& line);
inline void check(const std::string& section, const std::string& key)
{
assert (configs_.end()!=configs_.find(section) && configs_[section].end()!=configs_[section].find(key));
}
typedef std::map<std::string, std::string> KeyValue;
std::map<std::string, KeyValue> configs_;
std::string curSession_;
};
#include "IniConfig.h"
#include <iostream> //cerr
#include <fstream>
#include <vector>
#include <boost/algorithm/string/trim.hpp>
using namespace std;
IniConfig::IniConfig(const char* iniFile)
{
configs_[""]; // 默认session
ifstream ifs(iniFile);
if (!ifs)
{
cerr << "config file \"" << iniFile << "\" not found!";
exit(-1);
}
vector<string> lines;
string line;
while (!ifs.eof())
{
getline(ifs, line);
// 略去空行
if (line.empty())
continue;
// 略去注释行
if (line.size() >= 1 && (line[0]=='#' || line[0]==';') )
continue;
lines.push_back(line);
}
for (vector<string>::iterator iter = lines.begin();
iter != lines.end();
++iter)
{
parse_line(*iter);
}
ifs.close();
}
void IniConfig::parse_line(std::string& line)
{
// 消除头尾空格
boost::algorithm::trim(line);
size_t pos = line.rfind(']');
if (pos != string::npos)
{
assert(pos != 0);
if (pos != 1) //not [] but [session], add a section
{
curSession_ = line.substr(1, pos-1);
configs_[curSession_];
}
return;
}
else
{
pos = line.find('=');
assert(pos != string::npos);
string key, value;
{// 除去'='两边的空格和制表位
char* pTrim;
pTrim = &line[pos-1];
while (*pTrim==' ' || *pTrim=='\t')
pTrim--;
key.assign(&line[0], ++pTrim);
pTrim = &line[pos+1];
while (*pTrim==' ' || *pTrim=='\t')
pTrim++;
value.assign(pTrim);
}
//cout << key << "=" << value << endl;
configs_[curSession_].insert(KeyValue::value_type(key, value));
}
}