C++ 九阴真经之参数配置

筅森魡賤 提交于 2020-08-16 04:30:37

日常开发中参数配置是必不可少的,设计一种简单的参数文件格式及简易使用的接口就显得尤为重要。

配置文件格式设计

[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];
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!