C++ ini解析器
在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解析器的更多相关文章
- goconfig - INI 解析器
goconfig简介 goconfig是一个由Go语言开发的针对windows下常见的ini格式的配置文件解析器.该解析器在涵盖了所有ini文件操作的基础之上,又针对Go语言实际开发过程中遇到的一些需 ...
- Atiit 如何手写词法解析器
Atiit 如何手写词法解析器 1.1. 通过编程直接从正则->nfa->dfa->表驱动词法解析一条龙自动生成.那是用程序自动生成是需要这样的,自己手写完全不必要这么复杂1 1.2 ...
- configparser_配置解析器
configparser:配置解析器 import configparser config = configparser.ConfigParser() #配置文件 config[', 'Compres ...
- $Django Rest Framework-频率组件,解析器
1 频率组件 #自定义组件写频率认证(重点继承BaseThrottle) from rest_framework.throttling import BaseThrottle import time ...
- golang开发:类库篇(四)配置文件解析器goconfig的使用
为什么要使用goconfig解析配置文件 目前各语言框架对配置文件书写基本都差不多,基本都是首先配置一些基础变量,基本变量里面有环境的配置,然后通过环境变量去获取该环境下的变量.例如,生产环境跟测试环 ...
- python接口自动化测试 - configparser配置文件解析器详细使用
configparser简介 ConfigParser模块已在Python 3中重命名为configparser 该模块定义了ConfigParser类. ConfigParser类实现一种基本的配置 ...
- Python3-configparser模块-配置文件解析器
Python3中的configparser模块主要用于处理类似于windows ini 文件结构的配置文件 1.configparser模块提供实现基本配置语言的ConfigParser类 2.配置文 ...
- XML技术之DOM4J解析器
由于DOM技术的解析,存在很多缺陷,比如内存溢出,解析速度慢等问题,所以就出现了DOM4J解析技术,DOM4J技术的出现大大改进了DOM解析技术的缺陷. 使用DOM4J技术解析XML文件的步骤? pu ...
- AFN解析器里的坑
AFN框架是用来用来发送网络请求的,它的好处是可以自动给你解析JSON数据,还可以发送带参数的请求AFN框架还可以监测当前的网络状态,还支持HTTPS请求,分别对用的类为AFNetworkReacha ...
随机推荐
- AC日记——Number Sequence hdu 1711
Number Sequence Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- [AI开发]深度学习如何选择GPU?
机器推理在深度学习的影响下,准确性越来越高.速度越来越快.深度学习对人工智能行业发展的贡献巨大,这得益于现阶段硬件计算能力的提升.互联网海量训练数据的出现.本篇文章主要介绍深度学习过程中如何选择合适的 ...
- LINUX___的常用几个快捷键
linux下:ctrl-c 发送 SIGINT 信号给前台进程组中的所有进程.常用于终止正在运行的程序.ctrl-z 发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个进程.ctrl- ...
- Linux下使用mv重命名文件或者移动文件(增强版的工具为rename)
mv命令既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子:将/a目录移动到/b下,并重命名为c mv /a /b/c 例子:将文件A.txt重命名为B.txt mv ...
- Xcode: This device is no longer connected error
Quit the xcode and connect again will all right.
- JavaScript中的Math方法演示
<html> <head> <script type="text/javascript"> var num = 12.4; alert(Math ...
- Direct2D教程(三)简单几何图形
从本章开始,我们介绍D2D几何图形. D2D图形分类 Direct2D支持多种类型的几何图形,包括Simple Geometry(简单几何图形) 矩形 圆角矩形 椭圆 Path Geometry(路径 ...
- Android二维码工具zxing使用
二维码在我们生活中随处可见.在我眼里简直能够用"泛滥"来形容啦.那怎样在我们Android项目中扫描识别二维码或生成二维码图片呢? 我们通常使用的开源框架是zxing.在githu ...
- NYOJ 353 3D dungeon 【bfs】
题意:给你一个高L长R宽C的图形.每个坐标都能够视为一个方格.你一次能够向上.下.左,右,前,后任一方向移动一个方格, 可是不能向有#标记的方格移动. 问:从S出发能不能到达E,假设能请输出最少的移动 ...
- C 标准库 - <errno.h>
C 标准库 - <errno.h> 简介 C 标准库的 errno.h 头文件定义了整数变量 errno,它是通过系统调用设置的,在错误事件中的某些库函数表明了什么发生了错误.该宏扩展为类 ...