使用C++实现的简单ini文件操作

30 篇文章 1 订阅

因为经常使用配置文件,为了方便之后的使用,决定自己写一个功能比较齐全的操作ini类型的配置文件,因为是在linux 环境使用,所以是针对linux系统的文件。写代码加上测试,花了几天时间,博客记录一波。水平有限,可能有不少问题,希望大佬可以指正。如果有人想使用,一定要自己好好测试。。。

代码分为两个文件,头文件iniparser.h代码如下:

/*
[section]       //section 段
key = value     //item
程序说明:
    1、本程序提供的返回值为int类型的接口,成功都返回0,失败返回负的错误码
    2、支持按照string、int、double、boolean类型读写value
    3、支持一个section包含重复key,读取所有的value,但不支持重复key的写
    4、支持不包含section的配置文件
    5、支持添加item、section,删除item或整个section
    6、支持不同的注释符
    7、支持读取注释以及修改或添加注释(虽然可能没用)
*/
#ifndef __INIPARSER_H__
#define __INIPARSER_H__
#include <string>
#include <vector>
#include <map>

#define ERR_NOT_FOUND_SECTION   (-1)    //段不存在
#define ERR_NOT_FOUND_KEY       (-2)    //key不存在
#define ERR_PARSE_FAIL          (-3)    //解析失败
#define ERR_ALREADY_EXIST       (-4)    //段或者key已经存在
#define ERR_PARAMETER_INVALID   (-5)    //参数无效
#define ERR_FILE_OPERATION_FAIL (-6)    //打开、读写文件失败
#define ERR_LINE_TOO_LONG       (-7)    //文件的行过长

namespace iniparser
{

struct IniItem
{
    std::string key;
    std::string value;
    std::string upper_comment;  //上注释
    std::string right_comment;  //右注释
    std::string real_line;      //去掉换行后的实际内容
};
struct IniSection
{
    std::string name;
    std::string upper_comment;  //上注释
    std::string right_comment;  //右注释
    std::string real_line;      //去掉换行后的实际内容
    std::vector<IniItem *> items;
};

class CIniParser
{
public:
    CIniParser();
    ~CIniParser();

public:
    //导入文件
    int Load(const std::string &path);

    //修改注释符,默认为"#;"
    int SetCommentDelim(const std::string &delim);
    
    //写入文件,默认写入Load导入的文件
    int Save(const std::string &path = "");
    
    //获取string、int、double、boolean类型的值,对int和double不处理实际内容到底是不是数字字符串
    //对Boolean类型,“true”或者“1”返回true,“false”或者“0”返回false,“true”和“false”大小写都可以
    int GetStringValue(const std::string &section, const std::string &key, std::string *value);
    int GetIntValue(const std::string &section, const std::string &key, int *value);
    int GetDoubleValue(const std::string &section, const std::string &key, double *value);
    int GetBooleanValue(const std::string &section, const std::string &key, bool *value);

    //针对可能存在重复的key设计的,如果存在重复的key,返回所有的value
    int GetStringValues(const std::string &section, const std::string &key, std::vector<std::string> *values);
    int GetIntValues(const std::string &section, const std::string &key, std::vector<int> *values);
    int GetDoubleValues(const std::string &section, const std::string &key, std::vector<double> *values);
    int GetBooleanValues(const std::string &section, const std::string &key, std::vector<bool> *values);

    //获取所有的section
    int GetSections(std::vector<std::string> *sections);
    //获取某个section的所有的key
    int GetKeys(const std::string &section, std::vector<std::string> *keys);
    //获取某个段的所有的key和value,不支持重复的key
    int GetItems(const std::string &section, std::map<std::string, std::string> *items);

    //设置string、int、double、boolean类型的value值,不存在则添加,只有调用了Save后才能在文件中生效
    int SetStringValue(const std::string &section, const std::string &key, const std::string &value);
    int SetIntValue(const std::string &section, const std::string &key, int value);
    int SetDoubleValue(const std::string &section, const std::string &key, double value);
    int SetBooleanValue(const std::string &section, const std::string &key, bool value);

    //添加段
    int AddSection(const std::string &section);

    //删除整个段
    int DeleteSection(const std::string &section);
    //删除某条数据(key=value)
    int DeleteItem(const std::string &section, const std::string &key);
    
    bool HasSection(const std::string &section);
    bool HasKey(const std::string &section, const std::string &key);
    
    //与注释相关的接口,可能这些功能没啥用,哈哈。。。 just for fun
    //注意获取的注释是带有注释符号的,如果不想要注释符号,需要自己处理,哈哈
    int GetSectionUpperComment(const std::string &section, std::string *comment);
    int GetSectionRightComment(const std::string &section, std::string *comment);
    int GetItemUpperComment(const std::string &section, const std::string &key, std::string *comment);
    int GetItemRightComment(const std::string &section, const std::string &key, std::string *comment);
    //设置注释,只能设置单行的,如果有换行符,后果自负。。。。
    int SetSectionUpperComment(const std::string &section, const std::string &comment);
    int SetSectionRightComment(const std::string &section, const std::string &comment);
    int SetItemUpperComment(const std::string &section, const std::string &key, const std::string &comment);
    int SetItemRightComment(const std::string &section, const std::string &key, const std::string &comment);

    //打印,调试用的
    void Print();
    void PrintRaw();

private:

    void Release();
    IniSection *GetSection(const std::string &section);
    IniSection *ParseSectionLine(const std::string &line, const std::string &comment);
    IniItem *ParseItemLine(const std::string &line, const std::string &comment);
    std::string Trim(const std::string &s);
    bool SplitByComment(
        const std::string &line, const std::string &delim, std::string &left_str, std::string &right_comment);
    
private:

    std::string m_CommentDelim; //注释符
    std::string m_FilePath;     //导入的文件路径
    std::vector<IniSection *> m_Sections;
};

}

#endif

源文件iniparser.cpp如下:

#include "iniparser.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <algorithm>

#define LINE_MAX_SIZE 1024

//#define __DEBUG__
#ifdef __DEBUG__
#define print_info(format, ...)     do {\
        fprintf(stdout, "[" __FILE__ "][%s:%d] " format "\n", __FUNCTION__ ,  __LINE__, ##__VA_ARGS__); \
    } while(0)
#else
    #define print_info(format, ...)
#endif

namespace iniparser
{

CIniParser::CIniParser()
    : m_CommentDelim(";#")
{

}

CIniParser::~CIniParser()
{
    Release();
}

int CIniParser::Load(const std::string& path)
{
    if (path.empty())
        return ERR_PARAMETER_INVALID;

    //会不会是重新导入新的文件,先将之前的清空
    Release();
/*    std::string real_path;
    if (path[0] == '/' || path[0] == '.')     //如果是绝对路径或者以点开头的路径,直接使用该路径
    {
        real_path = path;
    }
    else    //否则使用$HOME/conf/作为前缀
    {
        char *conf_path = getenv("HOME");
        real_path = std::string(conf_path) + "/" + path;
    }
    m_FilePath = real_path;
*/
    m_FilePath = path;
    FILE *fp = fopen(m_FilePath.c_str(), "r");
    if (!fp)
    {
        print_info("fopen %s fail", m_FilePath.c_str());
        return ERR_FILE_OPERATION_FAIL;
    }

    char line[LINE_MAX_SIZE];
    //创建一个空段,用来保存文件开始可能存在的没有section的部分
    IniSection *pis = new IniSection();
    m_Sections.push_back(pis);
    std::string comment;
    while (fgets(line, sizeof(line), fp))
    {
        if (line[strlen(line) - 1] != '\n')
        {
            fclose(fp);
            return ERR_LINE_TOO_LONG;
        }

        std::string clean_line = Trim(line);
        //如果是空行或者开头是注释的行,都放到comment中
        if (clean_line.empty() || 
            find(m_CommentDelim.begin(), m_CommentDelim.end(), clean_line[0]) != m_CommentDelim.end())
        {
            comment += line;
            continue;
        }

        if (clean_line[0] == '[')
        {
            pis = ParseSectionLine(line, comment);
            if (!pis)
            {
                print_info("ParseSectionLine fail");
                fclose(fp);
                return ERR_PARSE_FAIL;
            }
            m_Sections.push_back(pis);
            comment.clear();
        }
        else
        {
            IniItem *pii = ParseItemLine(line, comment);
            if (!pii)
            {
                print_info("ParseItemLine fail");
                fclose(fp);
                return ERR_PARSE_FAIL;
            }
            pis->items.push_back(pii);
            comment.clear();
        }
    }
    fclose(fp);

    return 0;
}

int CIniParser::SetCommentDelim(const std::string &delim)
{
    if (delim.empty())
        return ERR_PARAMETER_INVALID;

    m_CommentDelim = delim;

    return 0;
}

int CIniParser::Save(const std::string &path)
{
    std::string real_path;
    if (path.empty())
    {
        real_path = m_FilePath;
    }
    else
    {
        real_path = path;
    }
    
    std::string data;

    for (std::vector<IniSection *>::const_iterator sec_citer = m_Sections.begin();
        sec_citer != m_Sections.end(); ++sec_citer)
    {
        if (!(*sec_citer)->upper_comment.empty())
        {
            data += (*sec_citer)->upper_comment;
        }
        if (!(*sec_citer)->real_line.empty())
        {
            data += (*sec_citer)->real_line;
        }
        for (std::vector<IniItem *>::const_iterator item_citer = (*sec_citer)->items.begin();
            item_citer != (*sec_citer)->items.end(); ++item_citer)
        {
            if (!(*item_citer)->upper_comment.empty())
            {
                data += (*item_citer)->upper_comment;
            }
            if (!(*item_citer)->real_line.empty())
            {
                data += (*item_citer)->real_line;
            }
        }
    }

    FILE *fp = fopen(real_path.c_str(), "w");
    if (!fp)
    {
        print_info("fopen %s fail", real_path.c_str());
        return ERR_FILE_OPERATION_FAIL;
    }

    size_t n = fwrite(data.c_str(), 1, data.size(), fp);
    if (n != data.size())
    {
        print_info("fwrite %s fail", real_path.c_str());
        fclose(fp);
        return ERR_FILE_OPERATION_FAIL;
    }
    fclose(fp);

    return 0;
}

int CIniParser::GetStringValue(const std::string &section, const std::string &key, std::string *value)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;

    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        if ((*item_citer)->key == key)
        {
            *value = (*item_citer)->value;
            return 0;
        }
    }
    return ERR_NOT_FOUND_KEY;
}

int CIniParser::GetIntValue(const std::string &section, const std::string &key, int *value)
{
    std::string v;
    int ret = GetStringValue(section, key, &v);
    if (ret != 0)
    {
        return ret;
    }
    else
    {
        *value = atoi(v.c_str());
        return 0;
    }
}

int CIniParser::GetDoubleValue(const std::string &section, const std::string &key, double *value)
{
    std::string v;
    int ret = GetStringValue(section, key, &v);
    if (ret != 0)
    {
        return ret;
    }
    else
    {
        *value = atof(v.c_str());
        return 0;
    }
}

int CIniParser::GetBooleanValue(const std::string &section, const std::string &key, bool *value)
{
    std::string v;
    int ret = GetStringValue(section, key, &v);
    if (ret != 0)
    {
        return ret;
    }
    else
    {
        if (!strcasecmp(v.c_str(), "true") || !strcasecmp(v.c_str(), "1"))
        {
            *value = true;
            return 0;
        }
        else if (!strcasecmp(v.c_str(), "false") || !strcasecmp(v.c_str(), "0"))
        {
            *value = false;
            return 0;
        }
        else
        {
            return ERR_PARSE_FAIL;
        }
    }
}

int CIniParser::GetStringValues(const std::string &section, const std::string &key, std::vector<std::string> *values)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;

    std::vector<std::string> vs;
    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        if ((*item_citer)->key == key)
        {
            vs.push_back((*item_citer)->value);
        }
    }
    if (vs.empty())
    {
        return ERR_NOT_FOUND_KEY;
    }
    else
    {
        *values = vs;
        return 0;
    }
}

int CIniParser::GetIntValues(const std::string &section, const std::string &key, std::vector<int> *values)
{
    std::vector<std::string> vs;
    int ret = GetStringValues(section, key, &vs);
    if (ret != 0)
    {
        return ret;
    }
    else
    {
        std::vector<int> vi;
        for (std::vector<std::string>::const_iterator citer = vs.begin();
            citer != vs.end(); ++citer)
        {
            vi.push_back(atoi(citer->c_str()));
        }
        *values = vi;
        return 0;
    }
}

int CIniParser::GetDoubleValues(const std::string &section, const std::string &key, std::vector<double> *values)
{
    std::vector<std::string> vs;
    int ret = GetStringValues(section, key, &vs);
    if (ret != 0)
    {
        return ret;
    }
    else
    {
        std::vector<double> vd;
        for (std::vector<std::string>::const_iterator citer = vs.begin();
            citer != vs.end(); ++citer)
        {
            vd.push_back(atof(citer->c_str()));
        }
        *values = vd;

        return 0;
    }
}

int CIniParser::GetBooleanValues(const std::string &section, const std::string &key, std::vector<bool> *values)
{
    std::vector<std::string> vs;
    int ret = GetStringValues(section, key, &vs);
    if (ret != 0)
    {
        return ret;
    }
    else
    {
        std::vector<bool> vb;
        for (std::vector<std::string>::const_iterator citer = vs.begin();
            citer != vs.end(); ++citer)
        {
            if (!strcasecmp(citer->c_str(), "true") || !strcasecmp(citer->c_str(), "1"))
            {
                vb.push_back(true);
            }
            else if (!strcasecmp(citer->c_str(), "false") || !strcasecmp(citer->c_str(), "0"))
            {
                vb.push_back(false);
            }
            else
            {
                return ERR_PARSE_FAIL;
            }
        }
        *values = vb;

        return 0;
    }
}

int CIniParser::GetSections(std::vector<std::string> *sections)
{
    std::vector<std::string> secs;
    for (std::vector<IniSection *>::const_iterator sec_citer = m_Sections.begin();
        sec_citer != m_Sections.end(); ++sec_citer)
    {
        //过滤掉第一个名为空的section
        if (!(*sec_citer)->name.empty())
        {
            secs.push_back((*sec_citer)->name);
        }
    }
    *sections = secs;

    return 0;
}

int CIniParser::GetKeys(const std::string &section, std::vector<std::string> *keys)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;

    std::vector<std::string> ks;
    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        ks.push_back((*item_citer)->key);
    }
    *keys = ks;

    return 0;
}

int CIniParser::GetItems(const std::string &section, std::map<std::string, std::string> *items)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;

    std::map<std::string, std::string> os;
    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        os[(*item_citer)->key] = (*item_citer)->value;
    }
    *items = os;

    return 0;
}

int CIniParser::SetStringValue(const std::string &section, const std::string &key, const std::string &value)
{
    if (key.empty() || value.empty())
        return ERR_PARAMETER_INVALID;

    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;

    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        if ((*item_citer)->key == key)
        {
            (*item_citer)->value = value;
            return 0;
        }
    }

    //如果不存在,创建
    IniItem *pii = new IniItem();
    pii->key = key;
    pii->value = value;
    pii->real_line = key + " = " + value + '\n';
    pis->items.push_back(pii);

    return 0;
}

int CIniParser::SetIntValue(const std::string &section, const std::string &key, int value)
{
    char buf[64];
    snprintf(buf, sizeof(buf), "%d", value);

    return SetStringValue(section, key, buf);
}

int CIniParser::SetDoubleValue(const std::string &section, const std::string &key, double value)
{
    char buf[64];
    snprintf(buf, sizeof(buf), "%f", value);

    return SetStringValue(section, key, buf);
}

int CIniParser::SetBooleanValue(const std::string &section, const std::string &key, bool value)
{
    if (value)
    {
        return SetStringValue(section, key, "true");
    }
    else
    {
        return SetStringValue(section, key, "false");
    }
}

int CIniParser::AddSection(const std::string &section)
{
    IniSection *pis = GetSection(section);
    if (pis != NULL)
        return ERR_ALREADY_EXIST;

    pis = new IniSection();
    pis->name = section;
    pis->real_line = std::string("[") + section + "]";
    m_Sections.push_back(pis);

    return 0;
}

int CIniParser::DeleteSection(const std::string &section)
{
    for (std::vector<IniSection *>::iterator sec_citer = m_Sections.begin();
        sec_citer != m_Sections.end(); ++sec_citer)
    {
        if ((*sec_citer)->name == section)
        {
            for (std::vector<IniItem *>::iterator item_citer = (*sec_citer)->items.begin();
                item_citer != (*sec_citer)->items.end(); )
            {
                delete *item_citer;
                item_citer = (*sec_citer)->items.erase(item_citer);
            }
            delete *sec_citer;
            m_Sections.erase(sec_citer);

            return 0;
        }
    }

    return ERR_NOT_FOUND_SECTION;
}

int CIniParser::DeleteItem(const std::string &section, const std::string &key)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;

    for (std::vector<IniItem *>::iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); )
    {
        if ((*item_citer)->key == key)
        {
            delete *item_citer;
            item_citer = pis->items.erase(item_citer);

            return 0;
        }
    }

    return ERR_NOT_FOUND_KEY;
}

bool CIniParser::HasSection(const std::string &section)
{
    if (GetSection(section) == NULL)
    {
        return false;
    }

    return true;
}

bool CIniParser::HasKey(const std::string &section, const std::string &key)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return false;

    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        if ((*item_citer)->key == key)
        {
            return true;
        }
    }

    return false;
}

int CIniParser::GetSectionUpperComment(const std::string &section, std::string *comment)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;
    
    if (!pis->upper_comment.empty() && 
        pis->upper_comment[pis->upper_comment.size() - 1] == '\n')
    {
        *comment = pis->upper_comment.substr(0, pis->upper_comment.size() - 1);
    }
    else
    {
        *comment = pis->upper_comment;
    }
    
    return 0;
}

int CIniParser::GetSectionRightComment(const std::string &section, std::string *comment)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;
    
    *comment = pis->right_comment;

    return 0;
}

int CIniParser::GetItemUpperComment(const std::string &section, const std::string &key, std::string *comment)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;
    
    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        if ((*item_citer)->key == key)
        {
            if (!(*item_citer)->upper_comment.empty() && 
                (*item_citer)->upper_comment[(*item_citer)->upper_comment.size() - 1] == '\n')
            {
                *comment = (*item_citer)->upper_comment.substr(0, (*item_citer)->upper_comment.size() - 1);
            }
            else
            {
                *comment = pis->upper_comment;
            }
            return 0;
        }
    }

    return ERR_NOT_FOUND_KEY;
}

int CIniParser::GetItemRightComment(const std::string &section, const std::string &key, std::string *comment)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;
    
    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        if ((*item_citer)->key == key)
        {
            *comment = (*item_citer)->right_comment;
            return 0;
        }
    }

    return ERR_NOT_FOUND_KEY;
}

int CIniParser::SetSectionUpperComment(const std::string &section, const std::string &comment)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;
    
    pis->upper_comment = m_CommentDelim[0] + comment + '\n';

    return 0;
}

int CIniParser::SetSectionRightComment(const std::string &section, const std::string &comment)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;

    pis->right_comment = m_CommentDelim[0] + comment;
    
    std::string::size_type index = pis->real_line.find_first_of(m_CommentDelim);
    if (index == std::string::npos)
    {
        //默认使用第一个注释符号
        pis->real_line = pis->real_line + " " + m_CommentDelim[0] + comment + '\n';
    }
    else
    {
        pis->real_line = pis->real_line.substr(0, index+1) + comment = '\n';
    }
    
    return 0;
}

int CIniParser::SetItemUpperComment(const std::string &section, const std::string &key, const std::string &comment)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;
    
    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        if ((*item_citer)->key == key)
        {
            (*item_citer)->upper_comment = m_CommentDelim[0] + comment + '\n';
            return 0;
        }
    }

    return ERR_NOT_FOUND_KEY;
}

int CIniParser::SetItemRightComment(const std::string &section, const std::string &key, const std::string &comment)
{
    IniSection *pis = GetSection(section);
    if (pis == NULL)
        return ERR_NOT_FOUND_SECTION;
    
    for (std::vector<IniItem *>::const_iterator item_citer = pis->items.begin();
        item_citer != pis->items.end(); ++item_citer)
    {
        if ((*item_citer)->key == key)
        {
            (*item_citer)->right_comment = m_CommentDelim[0] + comment;
            std::string::size_type index = (*item_citer)->real_line.find_first_of(m_CommentDelim);
            if (index == std::string::npos)
            {
                (*item_citer)->real_line = (*item_citer)->real_line + " " + m_CommentDelim[0] + comment;
            }
            else
            {
                (*item_citer)->real_line = (*item_citer)->real_line.substr(0, index+1) + comment;
            }
            
            return 0;
        }
    }

    return ERR_NOT_FOUND_KEY;
}

void CIniParser::Print()
{
    for (std::vector<IniSection *>::const_iterator sec_citer = m_Sections.begin();
        sec_citer != m_Sections.end(); ++sec_citer)
    {
        printf("section[%s]\n", (*sec_citer)->name.c_str());
        printf("upper_comment[%s]\n", (*sec_citer)->upper_comment.c_str());
        printf("right_comment[%s]\n", (*sec_citer)->right_comment.c_str());
        printf("items:\n");
        for (std::vector<IniItem *>::const_iterator item_citer = (*sec_citer)->items.begin();
            item_citer != (*sec_citer)->items.end(); ++item_citer)
        {
            printf("[%s=%s]\n", (*item_citer)->key.c_str(), (*item_citer)->value.c_str());
            printf("upper_comment[%s]\n", (*item_citer)->upper_comment.c_str());
            printf("right_comment[%s]\n", (*item_citer)->right_comment.c_str());            
        }
        printf("\n");
    }
}

//完全按照文件格式打印
void CIniParser::PrintRaw()
{
    for (std::vector<IniSection *>::const_iterator sec_citer = m_Sections.begin();
        sec_citer != m_Sections.end(); ++sec_citer)
    {
        if (!(*sec_citer)->upper_comment.empty())
        {
            printf("%s\n", (*sec_citer)->upper_comment.c_str());
        }
        if (!(*sec_citer)->real_line.empty())
        {
            printf("%s\n", (*sec_citer)->real_line.c_str());
        }
        for (std::vector<IniItem *>::const_iterator item_citer = (*sec_citer)->items.begin();
            item_citer != (*sec_citer)->items.end(); ++item_citer)
        {
            if (!(*item_citer)->upper_comment.empty())
            {
                printf("%s\n", (*item_citer)->upper_comment.c_str());
            }
            if (!(*item_citer)->real_line.empty())
            {
                printf("%s\n", (*item_citer)->real_line.c_str());
            }
        }
    }
}

void CIniParser::Release()
{
    for (std::vector<IniSection *>::iterator sec_citer = m_Sections.begin();
        sec_citer != m_Sections.end();)
    {
        for (std::vector<IniItem *>::iterator item_citer = (*sec_citer)->items.begin();
            item_citer != (*sec_citer)->items.end();)
        {
            delete *item_citer;
            item_citer = (*sec_citer)->items.erase(item_citer);
        }
        delete *sec_citer;
        sec_citer = m_Sections.erase(sec_citer);
    }
}

IniItem *CIniParser::ParseItemLine(const std::string &line, const std::string &comment)
{
    if (line.empty())
    {
        print_info("line is empty");
        return NULL;
    }

    std::string left_str;
    std::string right_comment;
    //按照注释符号,分解成内容和注释两部分
    SplitByComment(line, m_CommentDelim, left_str, right_comment);

    char key[LINE_MAX_SIZE];
    char value[LINE_MAX_SIZE];
    int n = sscanf(left_str.c_str(), "%[^= \t] = %s", key, value);
    if (n != 2)
    {
        print_info("sscanf get key=value [%s] fail", left_str.c_str());
        return NULL;
    }

    IniItem *pii = new IniItem();
    pii->key = std::string(key);
    pii->value = std::string(value);
    pii->right_comment = right_comment;
    pii->upper_comment = comment;
    pii->real_line = line;

    return pii;
}

IniSection *CIniParser::GetSection(const std::string &section)
{
    for (std::vector<IniSection *>::iterator sec_citer = m_Sections.begin();
        sec_citer != m_Sections.end(); ++sec_citer)
    {
        if ((*sec_citer)->name == section)
        {
            return *sec_citer;
        }
    }
    return NULL;
}

IniSection *CIniParser::ParseSectionLine(const std::string &line, const std::string &comment)
{
    if (line.empty())
    {
        print_info("line is empty");
        return NULL;
    }

    std::string left_str;
    std::string right_comment;
    //按照注释符号,分解成内容和注释两部分
    SplitByComment(line, m_CommentDelim, left_str, right_comment);

    char buf[LINE_MAX_SIZE];
    int n = sscanf(left_str.c_str(), "[ %[^] \t]", buf);
    if (n != 1)
    {
        print_info("sscanf get section fail");
        return NULL;
    }
    std::string::size_type index = left_str.find_first_of("]");
    if (index == std::string::npos)
    {
        print_info("can not find ], line[%s] left_str[%s]", line.c_str(), left_str.c_str());
        return NULL;
    }

    if (GetSection(std::string(buf)) != NULL)
    {
        print_info("section %s already exists", buf);
        return NULL;
    }
    IniSection *pis = new IniSection();
    pis->name = std::string(buf);
    pis->right_comment = right_comment;
    pis->upper_comment = comment;
    pis->real_line = line;

    return pis;
}

std::string CIniParser::Trim(const std::string& s)
{
    if (s.empty())
        return s;
  
    std::string s1 = s;
    std::string::iterator siter = s1.begin();  
    while (siter != s1.end())
    {
        if (isspace(*siter))
            siter = s1.erase(siter);
        else
            break;
    }
 
    if (s1.empty())
        return std::string();
 
    siter = s1.end();
    while (siter != s1.begin())
    {
        if (isspace(*--siter))
            siter = s1.erase(siter);
        else
            break;
    }
    return s1;
}

bool CIniParser::SplitByComment(
    const std::string &line, const std::string &delim, std::string &left_str, std::string &right_comment)
{
    std::string::size_type index = line.find_first_of(delim);
    //存在注释
    if (index != std::string::npos)
    {
        //right_comment里包含注释符号
        right_comment = Trim(line.substr(index));
        left_str = Trim(line.substr(0, index));
        return true;
    }
    else
    {
        //不存在注释
        left_str = Trim(line);
        right_comment.clear();
        return false;
    }
}

}

 

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值