简单的INI解析封装

简单封装的一个ini解析处理类(支持跨平台)。支持功能:

  1. 加载并解析指定ini文件中的配置;
  2. 读取指定 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);
  3. 支持新段、项、值写入;提示:如果写入的项是已经存在的,则为修改旧项值;
    示例:
     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 文件

如果对该封装有改进或不当之处,欢迎指定、交流!

上一篇:单源最短路径问题之dijkstra算法


下一篇:kamailio 云部署 配置NAT