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 ...
随机推荐
- OpenOPC
客户端连接OpenOPC Gateway import OpenOPC gateway='192.168.1.90' opchost='testbox' opcserv='KEPware.KEPSer ...
- hdu 1796(容斥原理+状态压缩)
How many integers can you find Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 65536/32768 ...
- 十六进制字符串jpg图片互转
十六制字符串jpg图片互转(格式:FFD8FFE000104A******)如:FFD8FFE000104A46494600010100000100010000FFDB0043000806060706 ...
- jQuery移动端手机键盘输入车牌号代码【附加新能源车牌】
最近在移动应用中要做到一个录取汽车牌号码的功能,在网上找了一个插件后发现没有增加新能源车牌功能, 和同事研究了一下,将其进行改造完美的实现了这个功能,这里放出该插件的源码: 原插件来自A5源码网[ht ...
- Codeforces Gym 100338H High Speed Trains 组合数学+dp+高精度
原题链接:http://codeforces.com/gym/100338/attachments/download/2136/20062007-winter-petrozavodsk-camp-an ...
- PyTorch学习笔记之Variable_and_function_cat
application 1 from torch.autograd import Variable import torch b = Variable(torch.FloatTensor([64, 1 ...
- Maven的POM简单理解
以下引用自官方的POM介绍https://maven.apache.org/guides/introduction/introduction-to-the-pom.html: 一.什么是POM? 项目 ...
- springboot多环境配置
springboot多环境(dev.test.prod)配置 2017-07-17 10:33 1290人阅读 评论(0) 收藏 举报 分类: spring boot(6) 版权声明:本文为博主原 ...
- Java常见面试题汇总(一)
1)什么是Java虚拟机?为什么Java被称作是"平台无关的编程语言"? Java虚拟机是一个能够运行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机运行的字节 ...
- word中更改图片和标题之间的垂直距离
word中插入图片后.往往须要给图片加上标题. 你插入图片和给图片插入标题时,word用的是默认的格式给你插入的图片和标题. 假如原来的paragraph是2倍行距.你的图片和标题之间的距离也是2倍行 ...