日常开发中参数配置是必不可少的,设计一种简单的参数文件格式及简易使用的接口就显得尤为重要。
配置文件格式设计
[System]
#周期
STSCycle=60
#延时分钟(单位:分)
DelayMin=0
#日志级别
LogLevel=2
该配置文件包括参数组、参数名、参数值、备注 四个元素,可以满足大部分日常开发中简单的参数配置需求。
#ifndef __APPCONFIG_H__
#define __APPCONFIG_H__
/***********************************************************
* @Description: 配置文件加载类
* 1、配置参数以行为单位
* 2、参数格式为:key = value
* 3、每一行最多支持255字节
* 4、以#开头的行表示注释
* 5、通过GETPARAM获取参数,参数为key、默认值, 默认值的类型即返回值的类型
* 6、支持类型const char*、std::string、int、double
* 示例:
CAppConfig::LoadConfigFile("config.ini");
int nPort = GETPARAM("group", "Port", 21);
std::string strUser = GETPARAM("group","User", "admin");
double fee = GETPARAM("group","Fee", 1.23);
************************************************************/
#include <map>
#include <vector>
#include <string>
#include "Singleton.h"
#define GETPARAM(group, param, defaultVal) CAppConfigAgent::get_instance().GetParam(group, param, defaultVal)
//参数转换类
template<typename T>
class ConvertParam
{
public:
ConvertParam(const std::string& paramValue):m_paramValue(paramValue)
{
}
T operator()()
{
return m_paramValue.c_str();
}
public:
const std::string& m_paramValue;
};
//参数转换(特化)类
template<>
class ConvertParam<const char*>
{
public:
ConvertParam(std::string& paramValue):m_paramValue(paramValue)
{
}
const char* operator()()
{
return m_paramValue.c_str();
}
public:
std::string& m_paramValue;
};
//参数转换(特化)类
template<>
class ConvertParam<int>
{
public:
ConvertParam(const std::string& paramValue):m_paramValue(paramValue)
{
}
int operator()()
{
return atoi(m_paramValue.c_str());
}
public:
const std::string& m_paramValue;
};
//参数转换(特化)类
template<>
class ConvertParam<double>
{
public:
ConvertParam(const std::string& paramValue):m_paramValue(paramValue)
{
}
double operator()()
{
return atof(m_paramValue.c_str());
}
public:
const std::string& m_paramValue;
};
class CAppConfig
{
public:
bool LoadConfigFile(const char* pszFileName);
void AddConfigItem(const std::map<std::string, std::map<std::string, std::string>>& mapConfig);
template<typename T>
T GetParam(const char* pszGroup, const char* pszParam, T value)
{
if (m_paramList.find(pszGroup) == m_paramList.end())
{
return value;
}
if (m_paramList[pszGroup].find(pszParam) == m_paramList[pszGroup].end())
{
return value;
}
return ConvertParam<T>(m_paramList[pszGroup][pszParam])();
}
std::string Trim(const std::string& val);
//根据前缀获取值列表
std::vector<std::string> GetParamByPrefix(const char* pszGroup, const char* pszPrefix);
std::vector<std::string> GetGroupVec();
std::map<std::string, std::string>& GetGroupMap(const char* pszGroup);
private:
typedef std::map<std::string, std::string> GROUPPARAM;
std::map<std::string, GROUPPARAM> m_paramList;
};
typedef Singleton<CAppConfig> CAppConfigAgent;
#endif //__APPCONFIG_H__
#include "AppConfig.h"
#include <fstream>
#include <iostream>
#include <memory.h>
//获取去除两端空格后的值
std::string CAppConfig::Trim(const std::string& val)
{
if ("" == val)
{
return "";
}
char *pszBuf = new char[val.length() + 1];
const char* pszTmpPtr = val.c_str();
const char* begPtr = pszTmpPtr;
const char* endPtr = pszTmpPtr + val.length() - 1;
while(begPtr < endPtr && ' ' == *begPtr)begPtr++;
while(begPtr < endPtr && ' ' == *endPtr)endPtr--;
memcpy(pszBuf, begPtr, endPtr - begPtr + 1);
pszBuf[endPtr - begPtr + 1] = 0;
std::string newVal(pszBuf);
delete[] pszBuf;
return newVal;
}
bool CAppConfig::LoadConfigFile(const char* pszFileName)
{
std::ifstream fin(pszFileName);
if (!fin)
{
return false;
}
char szBuf[4096] = {0};
std::string strGroup("Default");
while(fin.good())
{
memset(szBuf, 0, sizeof(szBuf));
fin.getline(szBuf,sizeof(szBuf));
std::string sigLineValue = Trim(szBuf);
//忽略空行
if (sigLineValue.size() == 0)
{
continue;
}
//以#号开头的行表示注释
if (sigLineValue[0] == '#')
{
continue;
}
if (sigLineValue[0] == '[' && sigLineValue[sigLineValue.size() - 1] == ']')
{
strGroup = sigLineValue.substr(1,sigLineValue.size() - 2);
continue;
}
char* pszEqualIdx = strstr(szBuf, "+=");
if (pszEqualIdx)
{
*pszEqualIdx = 0;
m_paramList[strGroup][Trim(szBuf)] += Trim(pszEqualIdx + 2);
continue;
}
pszEqualIdx = strstr(szBuf, "=");
if (!pszEqualIdx)
{
continue;
}
*pszEqualIdx = 0;
m_paramList[strGroup][Trim(szBuf)] = Trim(pszEqualIdx + 1);
}
return true;
}
void CAppConfig::AddConfigItem(const std::map<std::string, std::map<std::string, std::string>>& mapConfig)
{
for (auto iter = mapConfig.begin(); iter != mapConfig.end(); iter++)
{
const std::string& strGroup = iter->first;
const std::map<std::string, std::string>& mapParam = iter->second;
for (auto it = mapParam.begin(); it != mapParam.end(); it++)
{
m_paramList[strGroup][it->first] = it->second;
}
}
}
//根据前缀获取值列表
std::vector<std::string> CAppConfig::GetParamByPrefix(const char* pszGroup, const char* pszPrefix)
{
std::vector<std::string> valList;
if (m_paramList.find(pszGroup) == m_paramList.end())
{
return valList;
}
auto &group = m_paramList[pszGroup];
auto item = group.begin();
for (; item != group.end(); item++)
{
int n = item->first.find(pszPrefix);
if (0 == n)
{
valList.push_back(item->second);
}
}
return valList;
}
std::vector<std::string> CAppConfig::GetGroupVec()
{
std::vector<std::string> groupVec;
auto item = m_paramList.begin();
for (; item != m_paramList.end(); item++)
{
groupVec.push_back(item->first);
}
return groupVec;
}
std::map<std::string, std::string>& CAppConfig::GetGroupMap(const char* pszGroup)
{
return m_paramList[pszGroup];
}
来源:oschina
链接:https://my.oschina.net/u/3312209/blog/4306746