Chinaunix首页 | 论坛 | 博客
  • 博客访问: 283753
  • 博文数量: 41
  • 博客积分: 2630
  • 博客等级: 少校
  • 技术积分: 702
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-30 15:56
文章分类

全部博文(41)

文章存档

2012年(2)

2011年(2)

2010年(3)

2009年(26)

2008年(8)

我的朋友

分类: C/C++

2009-09-19 17:55:01

     INI文件格式可参考维基百科
[section]
;elem1
elem1 = 0
#elem2
elem2 = 1
...

   我实现的这个INI配置管理器功能比较简单,主要通过STL和Boost的相关类库来实现,并做了简单的测试。

IniConfig.h:

#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_;
};


IniConfig.cpp:

#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));
    }
}

阅读(3252) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~