简单的INI解析封装
简单封装的一个ini解析处理类(支持跨平台)。支持功能:
- 加载并解析指定ini文件中的配置;
- 读取指定 section 下的指定 key 的值。提示:支持按数值型读取,或按文本类型读取;
使用示例:auto fWidth = 480.0f;
auto fHeight = 320.0f; ns_ini::IniParser ini;
ini.open(strConfigFile.c_str());
fWidth = ini.readFloat("glview", "screen_width", fWidth);
fHeight = ini.readFloat("glview", "screen_height", fHeight); - 支持新段、项、值写入;提示:如果写入的项是已经存在的,则为修改旧项值;
示例:auto fWidth = 480.0f;
auto fHeight = 320.0f; ns_ini::IniParser ini;
ini.open(strConfigFile.c_str());
fWidth = ini.readFloat("glview", "screen_width", fWidth);
fHeight = ini.readFloat("glview", "screen_height", fHeight); ini.writeFloat("glview", "screen_height, 777.77f); // 将旧值修改为 777.77f
ini.writeInt("glview", "screen_height, 666); // 再次将旧值修改为 666
ini.writeText("glview", "screen_height, "jacc.kim"); // 再次将旧值修改为 文本"jacc.kim"
源码如下:
/****************************************************************************** I'm jacc.kim CreateDate: 2017-06-13 17:12:16
FileName : JKIniParser.h
Version : 1.00
Author : jacc.kim
Summary : ini parser wrapper ******************************************************************************/
#pragma once #include <list>
#include <map> namespace ns_ini
{ class Section; /******************************************************************************
* create : (jacc.kim) [06-13-2017]
* summary : class IniParser
******************************************************************************/
class IniParser
{
public:
void setIniFile(const char* const pcszIniFile);
bool open(const char* const pcszIniFile = nullptr);
bool save(const char* const pcszIniFile = nullptr);
void close(); unsigned int getSectionAmount() const;
bool isSectionExisted(const char* const pcszSection) const;
bool isParameterExisted(const char* const pcszSection, const char* const pcszParameter) const; int readInt(const char* const pcszSection, const char* const pcszKey, const int def = ) const;
unsigned int readUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int def = 0u) const;
bool readBool(const char* const pcszSection, const char* const pcszKey, const bool def = false) const;
float readFloat(const char* const pcszSection, const char* const pcszKey, const float def = 0.0f) const;
double readDouble(const char* const pcszSection, const char* const pcszKey, const double def = 0.0) const;
const char* readText(const char* const pcszSection, const char* const pcszKey, const char* const def = nullptr) const; // !!!note: write existed section & key, the old value will be replaced.
void writeInt(const char* const pcszSection, const char* const pcszKey, const int value);
void writeUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int value);
void writeBool(const char* const pcszSection, const char* const pcszKey, const bool value);
void writeFloat(const char* const pcszSection, const char* const pcszKey, const float value);
void writeDouble(const char* const pcszSection, const char* const pcszKey, const double value);
void writeText(const char* const pcszSection, const char* const pcszKey, const char* const value); bool remove(const char* const pcszSection, const char* const pcszKey);
bool remove(const char* const pcszSection);
void clear(); public:
IniParser();
~IniParser(); Section* getSection(const char* const pcszSection) const;
Section& operator[](const char* const pcszSection) const; private:
IniParser(const IniParser& rhs)/* = delete*/;
IniParser& operator=(const IniParser& rhs)/* = delete*/; void trimLeft(char*& p, char*& q);
void trimRight(char*& p, char*& q);
void trim(char*& p, char*& q);
void trimRN0(char*& p, char*& q);
bool isEndWithN(const char* p, const size_t nLength);
bool stringEqual(const char* p, const char* q, int nChar = INT_MAX) const;
bool isSectionName(char* p, char* q);
char* splitKeyValue(char* p, char* q);
void parseIniLine(char* szIniLine);
void addSection(char* szSectionName);
void addParameter(char* szKey, char* szValue); private:
typedef std::list<Section*> SectionList;
typedef SectionList::iterator SectionListIter; // key = section name, value = section's ptr
typedef std::map <std::string, SectionListIter> SectionMap; private:
std::string m_strIniFile; // ini file name
SectionList m_listSections; // all sections.
SectionMap m_mapSectionName; // section <--> index mapping.(only reference.) };//class IniParser }//namespace ns_ini
IniParser.h 文件
#include "JKIniParser.h" namespace ns_ini
{ /******************************************************************************
* create : (jacc.kim) [06-13-2017]
* summary : class Section
******************************************************************************/
class Section
{
public:
struct Parameter
{
std::string key;
std::string value;
};//struct Parameter typedef std::list<Parameter> ParameterList;
typedef ParameterList::iterator ParameterListIter;
typedef std::map<std::string, ParameterListIter> ParameterMap; public:
Section(const char* pcszSectionName) : m_strSectionName (pcszSectionName)
, m_listParameters ()
, m_mapParameterKeys()
{} ~Section() {
this->clear();
} const char* getSectionName() const {
return m_strSectionName.c_str();
} bool isParameterExisted(const char* const pcszKey) const {
return m_mapParameterKeys.find(pcszKey) != m_mapParameterKeys.end();
} Parameter& operator[](const char* const pcszKey) const {
auto iter = m_mapParameterKeys.find(pcszKey);
return *(iter->second);
} const char* read(const char* const pcszKey) {
const char* pcszRetValue = nullptr;
if (nullptr != pcszKey) {
auto iter = m_mapParameterKeys.find(pcszKey);;
if (m_mapParameterKeys.end() != iter) {
pcszRetValue = (*(iter->second)).value.c_str();
}
}
return pcszRetValue;
} bool write(const char* const pcszKey, const char* const pcszValue) {
auto iter = m_mapParameterKeys.find(pcszKey);
if (m_mapParameterKeys.end() == iter) {
Parameter param = { pcszKey, pcszValue };
m_listParameters.emplace_back(param);
m_mapParameterKeys[pcszKey] = --m_listParameters.end();
return true;
}
(*this)[pcszKey].value = pcszValue;
return true;
} bool remove(const char* pcszKey) {
auto bIsSuccess = false;
if (nullptr != pcszKey) {
auto iter = m_mapParameterKeys.find(pcszKey);
if (m_mapParameterKeys.end() != iter) {
m_listParameters.erase(iter->second);
m_mapParameterKeys.erase(iter);
bIsSuccess = true;
}
}
return bIsSuccess;
} void clear() {
m_listParameters.clear();
m_mapParameterKeys.clear();
} ParameterList& getAllParameters() {
return m_listParameters;
} private:
std::string m_strSectionName;
ParameterList m_listParameters;
ParameterMap m_mapParameterKeys; };//class Section ///////////////////////////////////////////////////////////////////////////////
// class IniParser
IniParser::IniParser() : m_strIniFile ("")
, m_listSections ()
, m_mapSectionName()
{ } IniParser::~IniParser() {
this->clear();
} void IniParser::setIniFile(const char* const pcszIniFile) {
if (nullptr == pcszIniFile) {
return;
}
m_strIniFile = pcszIniFile;
} bool IniParser::open(const char* const pcszIniFile/* = nullptr*/) {
auto bIsSuccess = false;
const char* pcszOpenFile = nullptr != pcszIniFile ? pcszIniFile : m_strIniFile.c_str();
if (nullptr == pcszOpenFile) {
return bIsSuccess;
}
if (nullptr != pcszIniFile) {
this->setIniFile(pcszIniFile);
}
this->clear();
auto pINIFile = fopen(pcszIniFile, "rb");
if (nullptr != pINIFile) {
bIsSuccess = true;
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
while (!feof(pINIFile)) {
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
fgets(szBuff, nBUFF_SIZE, pINIFile);
this->parseIniLine(szBuff);
}
fclose(pINIFile);
pINIFile = nullptr;
} return bIsSuccess;
} bool IniParser::save(const char* const pcszIniFile/* = nullptr*/) {
auto bIsSuccess = false;
const char* pcszSaveFile = nullptr != pcszIniFile ? pcszIniFile : m_strIniFile.c_str();
if (nullptr == pcszSaveFile) {
return bIsSuccess; // 没有可保存的路径
}
::remove(pcszSaveFile);
auto pINIFile = fopen(pcszSaveFile, "ab+");
if (nullptr != pINIFile) {
bIsSuccess = true;
auto iter = m_listSections.begin();
const auto iterend = m_listSections.end();
const size_t nBUFF_SIZE = ;
char szBuffer[nBUFF_SIZE];
Section* pSection = nullptr;
for (; iterend != iter;/* ++iter*/) {
pSection = *iter;
const char* pcszSectionName = pSection->getSectionName();
fputs("[", pINIFile);
fputs(pcszSectionName, pINIFile);
fputs("]\r\n", pINIFile);
auto& allParameters = (*iter)->getAllParameters();
auto listiter = allParameters.begin();
const auto listiterend = allParameters.end();
for (; listiterend != listiter; ++listiter) {
auto& param = *listiter;
memset((void*)szBuffer, 0x0L, nBUFF_SIZE);
memcpy(szBuffer, param.key.c_str(), param.key.length());
szBuffer[param.key.length()] = '=';
memcpy(szBuffer + param.key.length() + , param.value.c_str(), param.value.length());
const auto nEndPos = param.key.length() + + param.value.length();
szBuffer[nEndPos + ] = '\0';
fputs(szBuffer, pINIFile);
if (!this->isEndWithN(szBuffer, nEndPos + )) {
fputs("\r\n", pINIFile);
}
}
if (iterend != ++iter) {
fputs("\r\n", pINIFile);
}
}
fclose(pINIFile);
pINIFile = nullptr;
} return bIsSuccess;
} void IniParser::close() {
this->save();
this->clear();
this->setIniFile(nullptr);
} unsigned int IniParser::getSectionAmount() const {
return static_cast<unsigned int>(m_listSections.size());
} bool IniParser::isSectionExisted(const char* const pcszSection) const {
return nullptr != this->getSection(pcszSection);
} bool IniParser::isParameterExisted(const char* const pcszSection, const char* const pcszParameter) const {
auto pSection = this->getSection(pcszSection);
return nullptr != pSection && pSection->isParameterExisted(pcszParameter);
} int IniParser::readInt(const char* const pcszSection, const char* const pcszKey, const int def/* = 0*/) const {
int retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
if ( != sscanf(pcszText, "%d", &retValue)) {
retValue = def; // 读取失败.
}
}
return retValue;
} unsigned int IniParser::readUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int def/* = 0u*/) const {
unsigned int retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
if ( != sscanf(pcszText, "%u", &retValue)) {
retValue = def; // 读取失败.
}
}
return retValue;
} bool IniParser::readBool(const char* const pcszSection, const char* const pcszKey, const bool def/* = false*/) const {
bool retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
int iTempVal = ;
if ( == sscanf(pcszText, "%d", &iTempVal)) {
return == iTempVal ? false : true;
} else if (this->stringEqual(pcszText, "true")) {
return true;
} else {
return false;
}
}
return retValue;
} float IniParser::readFloat(const char* const pcszSection, const char* const pcszKey, const float def/* = 0.0f*/) const {
float retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
if ( != sscanf(pcszText, "%f", &retValue)) {
retValue = def; // 读取失败.
}
}
return retValue;
} double IniParser::readDouble(const char* const pcszSection, const char* const pcszKey, const double def/* = 0.0*/) const {
double retValue = def;
const char* pcszText = this->readText(pcszSection, pcszKey, nullptr);
if (nullptr != pcszText) {
if ( != sscanf(pcszText, "%lf", &retValue)) {
retValue = def; // 读取失败.
}
}
return retValue;
} const char* IniParser::readText(const char* const pcszSection, const char* const pcszKey, const char* const def/* = nullptr*/) const {
const char* pcszRetValue = def;
auto pSection = this->getSection(pcszSection);
if (nullptr != pSection) {
pcszRetValue = pSection->read(pcszKey);
}
return pcszRetValue;
} void IniParser::writeInt(const char* const pcszSection, const char* const pcszKey, const int value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%d", value);
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%u", value);
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeBool(const char* const pcszSection, const char* const pcszKey, const bool value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%d", value ? : );
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeFloat(const char* const pcszSection, const char* const pcszKey, const float value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%g", value);
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeDouble(const char* const pcszSection, const char* const pcszKey, const double value) {
const size_t nBUFF_SIZE = ;
char szBuff[nBUFF_SIZE];
memset((void*)szBuff, 0x0L, nBUFF_SIZE);
sprintf(szBuff, "%g", value);
this->writeText(pcszSection, pcszKey, szBuff);
} void IniParser::writeText(const char* const pcszSection, const char* const pcszKey, const char* const value) {
if (nullptr != pcszSection && nullptr != pcszKey && nullptr != value) {
auto iter = m_mapSectionName.find(pcszSection);
Section* pSection = nullptr;
if (m_mapSectionName.end() == iter) {
pSection = new (std::nothrow) Section(pcszSection);
if (nullptr == pSection) {
return;
}
m_listSections.emplace_back(pSection);
m_mapSectionName[pcszSection] = --m_listSections.end();
} else {
pSection = *(iter->second);
}
pSection->write(pcszKey, value);
}
} bool IniParser::remove(const char* const pcszSection, const char* const pcszKey) {
auto bIsSuccess = false;
if (nullptr != pcszSection) {
auto iter = m_mapSectionName.find(pcszSection);
if (m_mapSectionName.end() != iter) {
auto pSection = *(iter->second);
if (nullptr != pSection) {
bIsSuccess = pSection->remove(pcszKey);
}
}
}
return bIsSuccess;
} bool IniParser::remove(const char* const pcszSection) {
auto bIsSuccess = false;
if (nullptr != pcszSection) {
auto iter = m_mapSectionName.find(pcszSection);
if (m_mapSectionName.end() != iter) {
auto list_iter = iter->second;
Section* pSection = *list_iter;
if (nullptr != pSection) {
delete pSection;
pSection = nullptr;
}
m_listSections.erase(list_iter);
m_mapSectionName.erase(iter);
bIsSuccess = true;
}
}
return bIsSuccess;
} void IniParser::clear() {
auto iter = m_listSections.begin();
const auto iterend = m_listSections.end();
Section* pSection = nullptr;
for (; iterend != iter; ++iter) {
pSection = *iter;
if (nullptr != pSection) {
delete pSection;
pSection = nullptr;
}
}
m_listSections.clear();
m_mapSectionName.clear();
} Section* IniParser::getSection(const char* const pcszSection) const {
Section* pRetSection = nullptr;
auto iter = m_mapSectionName.find(pcszSection);
if (m_mapSectionName.end() != iter) {
pRetSection = *(iter->second);
}
return pRetSection;
} Section& IniParser::operator[](const char* const pcszSection) const {
auto iter = m_mapSectionName.find(pcszSection);
return *(*(iter->second));
} void IniParser::trimLeft(char*& p, char*& q) {
if (nullptr != p) {
while (' ' == *p && ++p <= q);
}
} void IniParser::trimRight(char*& p, char*& q) {
if (nullptr != q) {
while (' ' == *q && --q >= p);
}
} void IniParser::trim(char*& p, char*& q) {
this->trimLeft(p, q);
this->trimRight(p, q);
} void IniParser::trimRN0(char*& p, char*& q) {
if (nullptr != q) {
while (('\0' == *q || '\r' == *q || '\n' == *q) && --q >= p);
}
} bool IniParser::isEndWithN(const char* p, const size_t nLength) {
if ( == nLength) {
return false;
}
const char* q = p + nLength;
while ('\0' == *q && --q >= p);
return (q >= p) && ('\n' == *q);
} bool IniParser::stringEqual(const char* p, const char* q, int nChar/* = INT_MAX*/) const {
int n = ;
if (p == q) {
return true;
}
while (*p && *q && *p == *q && n < nChar) {
++p;
++q;
++n;
}
if ((n == nChar) || (*p == && *q == )) {
return true;
}
return false;
} bool IniParser::isSectionName(char* p, char* q) {
if (nullptr == p || nullptr == q) {
return false;
}
return '[' == *p && ']' == *q;
} char* IniParser::splitKeyValue(char* p, char* q) {
char* pRetEqualSignPos = p;
while ('=' != *pRetEqualSignPos && ++pRetEqualSignPos < q);
return pRetEqualSignPos;
} void IniParser::parseIniLine(char* szIniLine) {
char* p = szIniLine;
char* q = p + strlen(p);
this->trimRN0(p, q);
this->trim(p, q);
if (p < q) {
// 只有这种情况才需要处理.因为 p > q,肯定不需要处理,说明全都是空格.如果p = q也不需要处理,因为只有一个字符还需要处理什么?
*(q + ) = '\0';
if (this->isSectionName(p, q)) {
*q = '\0';
++p;
this->addSection(p);
} else {
char* szEqualSignPos = this->splitKeyValue(p, q);
if (szEqualSignPos > p && szEqualSignPos < q) {
*szEqualSignPos = '\0';
++szEqualSignPos;
this->addParameter(p, szEqualSignPos);
}
}
}
} void IniParser::addSection(char* szSectionName) {
auto iter = m_mapSectionName.find(szSectionName);
if (m_mapSectionName.end() != iter) {
// 已存在
auto listiter = iter->second;
m_listSections.emplace_back(*listiter);
m_listSections.erase(listiter);
m_mapSectionName.erase(iter);
m_mapSectionName[szSectionName] = --m_listSections.end();
return;
}
Section* pSection = new (std::nothrow) Section(szSectionName);
if (nullptr == pSection) {
return;
}
m_listSections.emplace_back(pSection);
m_mapSectionName[szSectionName] = --m_listSections.end();
} void IniParser::addParameter(char* szKey, char* szValue) {
if (m_listSections.empty()) {
return;
}
auto pSection = m_listSections.back();
pSection->write(szKey, szValue);
} }//namespace ns_ini
IniParser.cpp 文件
如果对该封装有改进或不当之处,欢迎指定、交流!
简单的INI解析封装的更多相关文章
- 简单的URL解析
简单的URL解析,直接举例说明了 function getUrl(){ //如果存在则取到来后面的参数,注意,?不需要取出,substring从1开始,否则取""; var qs ...
- 自己动手实现一个简单的JSON解析器
1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等.在 ...
- 非常简单的XML解析(SAX解析、pull解析)
这里只是把解析的数据当日志打出来了 非常简单的xml解析方式 package com.example.demo.service; import java.io.IOException; import ...
- INI解析模块的C++实现
INI文件格式是某些平台或软件上的配置文件的非正式标准,以节(section)和键(key)构成,常用于微软Windows操作系统中. 节(section) 节用方括号括起来,单独占一行,例如: [s ...
- FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- FFmpeg的HEVC解码器源代码简单分析:解析器(Parser)部分
===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...
- FFmpeg的H.264解码器源代码简单分析:解析器(Parser)部分
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
- 一个简单的json解析器
实现一个简单地json解析器. 两部分组成,词法分析.语法分析 词法分析 package com.mahuan.json; import java.util.LinkedList; import ja ...
- VS Extension+NVelocity系列(一)——构建一个简单的NVelocity解析环境
一.前言 本节我们将实际实现一个简单的NVelocity解析环境,以便为以后的实例做一些基本工作,虽然NVelocity如何使用已经属于老掉牙的话题,但我只能专门挑出来一章来做铺垫.人生就是这样无奈啊 ...
随机推荐
- MySQL 8.0 正式版 8.0.11 发布:比 MySQL 5.7 快 2 倍
ySQL 8.0 正式版 8.0.11 已发布,官方表示 MySQL 8 要比 MySQL 5.7 快 2 倍,还带来了大量的改进和更快的性能! 注意:从 MySQL 5.7 升级到 MySQL 8. ...
- 2017多校第6场 HDU 6096 String AC自动机
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6096 题意:给了一些模式串,然后再给出一些文本串的不想交的前后缀,问文本串在模式串的出现次数. 解法: ...
- 网站服务器压力Web性能测试(1):Apache Bench:Apache自带服务器压力测试工具
一个网站或者博客到底能够承受多大的用户访问量经常是我们在用VPS或者独立服务器搭建网站了最关心的问题,还有不少人喜欢对LNMP或者LAMP进行一些优化以便提高Web性能,而优化后到底有多大的效果,就需 ...
- django开发项目实例3--用session是实现简单的登陆、验证登陆和注销功能
如果你的网页不是纯阅读型的,那么你很有可能希望在用户打开某些界面的时候需要验证用户是否登陆的信息, 虽然django里面有自带的一些user的类,但我看不懂,并且自己实现也不是很难,下面和大家分享一下 ...
- HDU-2389
Rain on your Parade Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 655350/165535 K (Java/Ot ...
- poj 1724(最短路+优先队列)
ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13436 Accepted: 4921 Descriptio ...
- Spring学习(一)——Spring中的依赖注入简介
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...
- CSS Modules入门及React中实践(内附webpack4配置)
本篇文章以整理为主,自己进行了部分修改,如有侵权,请告知 CSS Modules介绍 CSS Modules是什么东西呢?首先,让我们从官方文档入手:GitHub – css-modules/css- ...
- CentOS7安装配置WPS
1.下载 地址:http://wps-community.org/downloads 2.安装 rpm -ivh wps-office-10.1.0.5707-1.a21.x86_64.rpm 3.运 ...
- 六十六 aiohttp
asyncio可以实现单线程并发IO操作.如果仅用在客户端,发挥的威力不大.如果把asyncio用在服务器端,例如Web服务器,由于HTTP连接就是IO操作,因此可以用单线程+coroutine实现多 ...