在gitee上找到的一个很好用的ini文件解析器,纯C++代码,移植方便。

  项目地址:https://gitee.com/sollyu/IniParser

  稍微修改了下,去掉了Windows平台相关定义,改了下类名称。

  头文件:

 #ifndef INIPARSER_H
#define INIPARSER_H #include <map>
#include <string>
#include <string.h> class IniDoc
{
public:
struct IgnoreCaseLT
{
bool operator()(const std::string& lhs, const std::string& rhs) const
{
return strcasecmp(lhs.c_str(), rhs.c_str()) < ;
}
}; public:
typedef std::map<std::string, std::string, IgnoreCaseLT> KeyMap;
typedef std::map<std::string, KeyMap, IgnoreCaseLT> SectionMap;
typedef KeyMap::iterator KeyIterator;
typedef SectionMap::iterator SectionIterator; public:
// 默认的构造函数和析构函数
IniDoc();
~IniDoc(); // 构造函数 - 加载文件
IniDoc(const std::string& file_name); // 加载一个ini文件, 如果之前的文件被修改, 那么之前的ini文件将会被保持。
bool load(const std::string& file_name); // 从字符串中作为ini文件加载
bool loadString(const std::string& str); // 保持到加载ini位置
bool save(); // 另存为一个和加载路径不一样的文件中
bool saveAs(const std::string& file_name); // 返回ini是否被修改, 或者他最后一次操作是保存
bool isModified() const { return m_modified; } public: // high level member function. // 下面的成员函数是从Section中获得一些值
long getInteger(const std::string& section, const std::string& key, long def_val);
float getFloat(const std::string& section, const std::string& key, float def_val);
long getStruct(const std::string& section, const std::string& key, void* buffer, long size);
long getString(const std::string& section, const std::string& key, const std::string& def_val, std::string& buffer);
const std::string getString(const std::string& section, const std::string& key, const std::string& def_val); void setInteger(const std::string& section, const std::string& key, long value);
void setFloat(const std::string& section, const std::string& key, float value);
void setStruct(const std::string& section, const std::string& key, const void* buffer, long size);
void setString(const std::string& section, const std::string& key, const std::string& value); public:
bool delSection( const std::string& section );
bool delKey( const std::string& section, const std::string& key ); public:
// 返回一个section的map键值对
const KeyMap& getSection(const std::string& section) const; // 返回整个ini的Sections
const SectionMap& getIni() const { return m_map; } private:
void saveBeforeLoad();
const char* key_value(const std::string& section, const std::string& key); private:
// 禁止复制构造函数和赋值操作符。
IniDoc(const IniDoc& copy);
IniDoc& operator=(const IniDoc& rhs); private:
static const KeyMap ms_emptySection;
static const char left_tag ;
static const char right_tag ;
static const char equal ;
static const char cr ;
static const char new_line ;
static const char* empty_str ;
static const int BUFFER_LEN ; SectionMap m_map;
std::string m_file_name;
bool m_modified;
}; #endif // INIPARSER_H

  源文件:

 #include "IniDoc.h"

 #include <fstream>
#include <strstream> using namespace std; const char IniDoc::left_tag = '[' ;
const char IniDoc::right_tag = ']' ;
const char IniDoc::equal = '=' ;
const char IniDoc::cr = '\r';
const char IniDoc::new_line = '\n';
const char* IniDoc::empty_str = "" ;
const int IniDoc::BUFFER_LEN = ; const IniDoc::KeyMap IniDoc::ms_emptySection; IniDoc::IniDoc() : m_modified(false)
{ } IniDoc::IniDoc(const std::string& file_name) : m_modified(false)
{
load(file_name);
} IniDoc::~IniDoc()
{
if(m_modified)
save();
} void IniDoc::saveBeforeLoad()
{
if(m_modified)
save(); m_file_name.resize(); m_map.clear(); m_modified = false;
} const char* IniDoc::key_value(const std::string& section, const std::string& key)
{
SectionIterator itSection = m_map.find(section);
if(m_map.end() != itSection)
{
KeyIterator itKey = itSection->second.find(key);
if(itKey != itSection->second.end())
return itKey->second.c_str();
} return ;
} bool IniDoc::load(const std::string& file_name)
{
saveBeforeLoad(); ifstream file(file_name);
if(!file)
return false; file.seekg(, ios::end);
long len = file.tellg();
if(len < )
return false; char* buffer = new char[len + ];
if( == buffer)
return false; file.seekg(, ios::beg);
file.read(buffer, len); buffer[len = file.gcount()] = ; loadString(buffer);
m_file_name = file_name; delete[] buffer; return true;
} bool IniDoc::loadString(const std::string& str)
{
saveBeforeLoad(); unsigned long length = str.size(); if (str.size() == )
return false; enum status
{
after_left_tag,
after_section_name,
after_section_name_ws,
after_key_name,
after_key_name_ws,
after_equal,
start
}; string section; // 当前 section.
string key; // 当前 key.
status sta = start; // 解析状态.
const char* p = str.c_str(); // 当前解析字符串的位置.
const char* beg = p; // 当前元素的开始.
const char* last_ws = p; // 最后一个空格字符. for(; length; ++p, --length)
{
if(new_line == *p)
{
if(after_equal == sta)
{
if(cr == *(p - ))
--p; m_map[section][key] = string(beg, p - beg); if(cr == *p)
++p;
}
sta = start;
}
else
{
switch(sta)
{
case after_left_tag:
if(right_tag == *p)
{
sta = start;
section = empty_str; // empty section name.
}
else if(!isspace((unsigned char)*p))
{
sta = after_section_name;
beg = p;
}
break;
case after_section_name:
if(right_tag == *p)
{
sta = start;
section = string(beg, p - beg);
}
else if(isspace((unsigned char)*p))
{
sta = after_section_name_ws;
last_ws = p;
}
break;
case after_section_name_ws:
if(right_tag == *p)
{
sta = start;
section = string(beg, last_ws - beg);
}
else if(!isspace((unsigned char)*p))
{
sta = after_section_name;
}
break;
case after_key_name:
if(equal == *p)
{
sta = after_equal;
key = string(beg, p - beg);
beg = p + ;
}
else if(isspace((unsigned char)*p))
{
sta = after_key_name_ws;
last_ws = p;
}
break;
case after_key_name_ws:
if(equal == *p)
{
sta = after_equal;
key = string(beg, last_ws - beg);
beg = p + ;
}
else if(!isspace((unsigned char)*p))
{
sta = after_key_name;
}
break;
case start:
if(left_tag == *p)
{
sta = after_left_tag;
}
else if(equal == *p)
{
key = empty_str; // an empty key.
sta = after_equal;
beg = p + ;
}
else if(!isspace((unsigned char)*p))
{
sta = after_key_name;
beg = p;
}
break;
}
}
} if(after_equal == sta)
m_map[section][key] = string(beg, p - beg); return true;
} bool IniDoc::save()
{
if(==m_file_name.c_str() || ==m_file_name[])
return false; // file name invalid ofstream file(m_file_name.c_str());
if(!file)
return false; for(SectionMap::iterator itApp=m_map.begin(); itApp!=m_map.end(); ++itApp)
{
file << left_tag << itApp->first << right_tag << endl; for(KeyMap::iterator itKey=itApp->second.begin(); itKey!=itApp->second.end(); ++itKey)
file << itKey->first << equal << itKey->second << endl; file << endl;
}
m_modified = false; return true;
} bool IniDoc::saveAs(const std::string& file_name)
{
string old_file_name = m_file_name;
m_file_name = file_name; if(save())
return true; m_file_name = old_file_name;
return false;
} long IniDoc::getInteger(const std::string& section, const std::string& key, long def_val)
{
istrstream(key_value(section, key)) >> def_val;
return def_val;
} float IniDoc::getFloat(const std::string& section, const std::string& key, float def_val)
{
istrstream(key_value(section, key)) >> def_val;
return def_val;
} long IniDoc::getStruct(const std::string& section, const std::string& key_, void* buffer, long size)
{
std::string key = key_value(section, key_); if (key.size() == )
return ; const char* p = key.c_str();
char* dst = (char*)buffer;
long read_len = ;
char value; while(*p && read_len<size)
{
switch(*p)
{
case '': case '': case '': case '': case '':
case '': case '': case '': case '': case '':
value = *p - '';
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
value = *p - 'a' + ;
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
value = *p - 'A' + ;
break;
default:
return read_len;
} if( == (p - key.c_str())%)
*(dst + read_len) = value << ;
else
*(dst + read_len) = (*(dst + read_len) & 0xf0) + value; if( == (++p - key.c_str())%)
++read_len;
} return read_len;
} long IniDoc::getString(const std::string& section, const std::string& key_, const std::string& def_val, std::string& dst_str)
{
std::string key = key_value(section, key_);
dst_str = key.length() ? key : def_val;
return dst_str.length();
} const std::string IniDoc::getString(const std::string& section, const std::string& key_, const std::string& def_val)
{
std::string key = key_value(section, key_);
if(key.length() == )
key = def_val; return key;
} void IniDoc::setInteger(const std::string& section, const std::string& key, long value)
{
char buffer[BUFFER_LEN + ];
ostrstream ostr(buffer, BUFFER_LEN);
ostr << value;
buffer[ostr.pcount()] = ;
setString(section, key, buffer);
} void IniDoc::setFloat(const std::string& section, const std::string& key, float value)
{
char buffer[BUFFER_LEN + ];
ostrstream ostr(buffer, BUFFER_LEN);
ostr << value;
buffer[ostr.pcount()] = ;
setString(section, key, buffer);
} inline char bin2hex(char bin)
{
return bin< ? bin+'' : bin-+'A';
} void IniDoc::setStruct(const std::string& section, const std::string& key, const void* buffer, long size)
{
char* dst = new char[size* + ];
if(dst)
{
const char* src = (const char*)buffer;
long i=;
for(i=; i<size; ++i)
{
dst[i << ] = bin2hex((src[i] >> ) & 0x0f );
dst[(i << ) + ] = bin2hex(src[i] & 0x0f);
} dst[i << ] = ;
setString(section, key, dst); delete[] dst;
}
} void IniDoc::setString(const std::string& section, const std::string& key, const std::string& value)
{
m_map[section][key] = value;
m_modified = true;
} bool IniDoc::delSection( const std::string& section )
{
SectionIterator itSection = m_map.find(section);
if(m_map.end() != itSection)
{
m_map.erase(itSection);
return true;
}
return false;
} bool IniDoc::delKey( const std::string& section, const std::string& key )
{
SectionIterator itSection = m_map.find(section);
if(m_map.end() != itSection)
{
KeyIterator itKey = itSection->second.find(key);
if(itKey != itSection->second.end())
{
itSection->second.erase(itKey);
return true;
}
}
return false;
} const IniDoc::KeyMap& IniDoc::getSection(const std::string& section) const
{
SectionMap::const_iterator itApp = m_map.find(section);
return m_map.end()==itApp ? ms_emptySection : itApp->second;
}

  

C++ ini解析器的更多相关文章

  1. goconfig - INI 解析器

    goconfig简介 goconfig是一个由Go语言开发的针对windows下常见的ini格式的配置文件解析器.该解析器在涵盖了所有ini文件操作的基础之上,又针对Go语言实际开发过程中遇到的一些需 ...

  2. Atiit 如何手写词法解析器

    Atiit 如何手写词法解析器 1.1. 通过编程直接从正则->nfa->dfa->表驱动词法解析一条龙自动生成.那是用程序自动生成是需要这样的,自己手写完全不必要这么复杂1 1.2 ...

  3. configparser_配置解析器

    configparser:配置解析器 import configparser config = configparser.ConfigParser() #配置文件 config[', 'Compres ...

  4. $Django Rest Framework-频率组件,解析器

    1 频率组件 #自定义组件写频率认证(重点继承BaseThrottle) from rest_framework.throttling import BaseThrottle import time ...

  5. golang开发:类库篇(四)配置文件解析器goconfig的使用

    为什么要使用goconfig解析配置文件 目前各语言框架对配置文件书写基本都差不多,基本都是首先配置一些基础变量,基本变量里面有环境的配置,然后通过环境变量去获取该环境下的变量.例如,生产环境跟测试环 ...

  6. python接口自动化测试 - configparser配置文件解析器详细使用

    configparser简介 ConfigParser模块已在Python 3中重命名为configparser 该模块定义了ConfigParser类. ConfigParser类实现一种基本的配置 ...

  7. Python3-configparser模块-配置文件解析器

    Python3中的configparser模块主要用于处理类似于windows ini 文件结构的配置文件 1.configparser模块提供实现基本配置语言的ConfigParser类 2.配置文 ...

  8. XML技术之DOM4J解析器

    由于DOM技术的解析,存在很多缺陷,比如内存溢出,解析速度慢等问题,所以就出现了DOM4J解析技术,DOM4J技术的出现大大改进了DOM解析技术的缺陷. 使用DOM4J技术解析XML文件的步骤? pu ...

  9. AFN解析器里的坑

    AFN框架是用来用来发送网络请求的,它的好处是可以自动给你解析JSON数据,还可以发送带参数的请求AFN框架还可以监测当前的网络状态,还支持HTTPS请求,分别对用的类为AFNetworkReacha ...

随机推荐

  1. KeyStore和TrustStore

    笔者的这篇文章参考了http://docs.oracle.com/cd/E19509-01/820-3503/ggfgo/index.html KeyStore和TrustStore在很多HTTPS双 ...

  2. Excel文件处理Demo

    1.BLL业务逻辑代码 /// <summary> /// 处理“店铺竞品销售数据”导入文件 /// </summary> /// <param name="f ...

  3. exec: "docker-proxy": executable file not found in $PATH

    在执行 docker run 操作的时候,一直报如下错误: [root@etcd1 vagrant]# docker run --name redis-6379 -p 6379:6379 -d --r ...

  4. django忘记超级用户密码的解决方法

    用Django shell: 1 python manage.py shell 然后获取你的用户名,并且重设密码: 1 2 3 4 from django.contrib.auth.models im ...

  5. CapIp.pas

    unit CapIp; interface uses Windows, Messages,Classes,winsock,sysutils; const WM_CapIp = WM_USER + ; ...

  6. AngularJS的Foreach循环示例

    代码下载:https://files.cnblogs.com/files/xiandedanteng/angularJSForeach.rar 代码: <!DOCTYPE HTML PUBLIC ...

  7. C++ 继承与接口 知识点 小结(一)

    [摘要] 要求理解覆盖.重载.隐藏的概念与相互之间的差别.熟记类继承中对象.函数的訪问控制:掌握虚函数.虚函数表.虚函数指针的联系:理解区分虚函数和虚继承在虚方法.虚指针在空间分配上的重点与难点:熟练 ...

  8. youtube-dl取代you-get?

    以前了解到you-get这个项目,支持超多视频网站下载,不过偶尔会出各种问题. 今天看到依云的博客文章:放弃 you-get,转投 youtube-dl 然后特地看了youtube-dl的支持列表:h ...

  9. OA权限树搭建 代码

    <ul id="tree"> <s:iterator value="#application.topPrivilegeList"> &l ...

  10. 【每日Scrum】第三天(4.24) TD学生助手Sprint2站立会议

    站立会议 组员 昨天 今天 困难 签到 刘铸辉 (组长) 今天主要看了多事件处理的内容然后改了下界面, 和小楠重写架构,使代码更加简洁,并增加了几个界面 架构太难,数据库字段总出问题 Y 刘静 添加事 ...