在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. hdu3947 给一些已知(需费用)路径去覆盖一些边 //预先加灌法费用流

    River Problem 题意:一个有向树(河流),只有一个汇点1,每条边只有一个出度.有些河道有污染指数xi,必需要治理,有m段路径,可以去覆盖这些,每被覆盖一次,xi降低响应值. :即 给出一些 ...

  2. XA事务与MySQL

    XA事务就是两阶段提交的一种实现方式 XA规范主要定义了事务管理器TM,和资源管理器RM之间的接口 根据2PC的规范,将一次事务分割成两个阶段 1. prepare阶段 TM向所有RM发送prepar ...

  3. HDU 4691

    http://acm.hdu.edu.cn/showproblem.php?pid=4691 留个板子. #include <iostream> #include <cstdio&g ...

  4. HDU 5212 Code【莫比乌斯反演】

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5212 题意: 给定序列,1≤i,j≤n,求gcd(a[i],a[j])∗(gcd(a[i],a[j] ...

  5. 详解Java中的字符串

    字符串常量池详解 在深入学习字符串类之前, 我们先搞懂JVM是怎样处理新生字符串的. 当你知道字符串的初始化细节后, 再去写String s = "hello"或String s ...

  6. BZOJ3295动态逆序对

    一道比较傻的CDQ分治 CDQ: 主要用于解决三位偏序的问题 #include<cstdio> #include<cctype> #include<algorithm&g ...

  7. 【mac IntelliJ Idea】mac上 idea快速重写父类方法 快捷键

    windows上快捷键: Ctrl+O Mac上快捷键: command+O 在要重写父类方法的位置 ,按下快捷键,然后选择要重写的方法即可.

  8. 两点C#的propertyGrid的使用心得【转】

    源文:http://www.cnblogs.com/bicker/p/3318934.html 最近接触C#的PropertyGrid比较多,得到了两个小心得记录一下. 第1点是关于控制Propert ...

  9. pandas常见函数详细使用

    groupby函数 pandas提供了一个灵活高效的groupby功能,它使你能以一种自然的方式对数据集进行切片.切块.摘要等操作,根据一个或多个键(可以是函数.数组.Series或DataFrame ...

  10. hough变换检测直线和圆

    图像测量和机器视觉作业: 提取图像中的直线和点的位置坐标,将其按一定顺序编码存入一文本文件,并在原图像上叠加显示出来. 下午实验了一下: 程序环境:vs2013(活动平台为x64)+opencv3.1 ...