ini解析器

2021-08-06  本文已影响0人  码农练功房

项目中需要用到解析ini格式的配置,手撸了一个:

static bool Startwith(const string&src, const string&str)
{
    return src.compare(0, str.size(), str) == 0;
}

static void Trim(string &s)  //去除字符两端空格
{
    if (s.empty())
    {
        return;
    }
    s.erase(0, s.find_first_not_of(" "));
    s.erase(s.find_last_not_of(" ") + 1);
}

class IniFileParser
{
public:
    IniFileParser(const string& data)
    {
        istringstream strin(data);
        string line;
        while (getline(strin, line, '\n'))// 将字符以行形式存储;
        {
            Trim(line);
            //默认以 '#', '-', '/', ';'开头的行为注释,过滤掉这些注释;
            if (Startwith(line, "#") || Startwith(line, "-") || Startwith(line, "/") || Startwith(line, ";"))
                continue;
            lines.push_back(line);
        }
    }

    string GetValue(const char* sectionName, const string&key)
    {
        UpdateContent(sectionName);
        auto iter = content.find(key);
        if (iter != content.end())
            return iter->second;
        return string();
    }
private:
    vector<string>::const_iterator FindSectionBeg(const char* sectionName)
    {
        string sectionTitle = string("[") + string(sectionName) + string("]");
        return find(lines.begin(), lines.end(), sectionTitle);
    }

    vector<string>::const_iterator FindSectionEnd(const char* sectionName)
    {
        auto lineBeg = FindSectionBeg(sectionName);
        if (lineBeg == lines.end())
            return lines.end();
        auto iter = lineBeg + 1;  // 另起一行,找下一个section
        for (; iter != lines.end(); ++iter)
        {
            const string& line = *iter;
            if (Startwith(line, "["))
                return iter;
        }
        // 没有找到下一个section,说明sectionName已经是最后一个section
        return lines.end();
    }

    void UpdateContent(const char* sectionName)
    {
        auto lineBeg = FindSectionBeg(sectionName);
        auto lineEnd = FindSectionEnd(sectionName);
        FillContent(lineBeg, lineEnd);
    }

    void FillContent(vector<string>::const_iterator beg, 
                     vector<string>::const_iterator end)
    {
        content.clear();
        vector<string>::const_iterator iter = beg;
        for (; iter != end; ++iter)
        {
            const string& line = *iter;
            string::size_type pos = line.find("=");
            if (pos == string::npos)
                continue;
            string key = line.substr(0, pos);
            Trim(key);
            string value = line.substr(pos + 1);
            Trim(value);
            content[key] = value;
        }
    }
private:
    vector<string> lines;  // 包含空行
    map<string, string> content; // section的key value数据;
};

要解析的ini文件内容:

[mysql]
addr=127.0.0.1
user=root
psw=root
port=3306
dbname=db

以下是IniFileParser使用demo:

int main()
{
    string path = GetCfgFilePath();  // GetCfgFilePath自己实现
    ifstream inputFile(path, ios::in);
    if (!inputFile.is_open())
    {
        return 0;
    }
    std::string fileData((std::istreambuf_iterator<char>(inputFile)), std::istreambuf_iterator<char>());
    IniFileParser iniParser(fileData);
    
    string ip = iniParser.GetValue("mysql", "addr");
    string userName = iniParser.GetValue("mysql", "user");
    string password = iniParser.GetValue("mysql", "psw");
    string strPort = iniParser.GetValue("mysql", "port");
    string dbName = iniParser.GetValue("mysql", "dbname");
    return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读