confparse

#example.conf
key0=v0
key1=v1,v2
[TT]
key2=v2
key3=v3

#example1.conf
key0=v0
key1=v1,v2
key3=v3

/*************************************************************************
    > File Name: confparse.h
    > Author: wangzhicheng
    > Mail: 2363702560@qq.com 
    > Created Time: Wed 12 Jul 2017 08:29:26 PM AWST
 ************************************************************************/
#ifndef CONF_PARSE_H
#define CONF_PARSE_H
#include <string>
#include <vector>
#include <map>
#include <set>
#include <fstream>
#include <sstream>
#include <algorithm>
namespace confparse
{
using namespace std;
class ConfParse;
class InnerKey
{
	friend class ConfParse;
private:
	map<string, set<string> >m_mapInner;	// key -- inner key value -- inner value
private:
	inline void Insert(const string &key, const set<string>&value)
	{
		m_mapInner.insert(make_pair(key, value));
	}
	inline void Clear()
	{
		m_mapInner.clear();
	}
	inline bool Empty()
	{
		return m_mapInner.empty();
	}
	void GetValue(const string &key, vector<string>&value);
};
class ConfParse
{
private:
	char m_cCommentChar;					// comment line generally #
	char m_cSplitChar_kv;					// split char between key and value generally =
	char m_cSplitChar_vv;					// split char between value and value generally ,
	map<string, InnerKey>m_mapConf;			// key -- outside key
public:
	ConfParse(char comment = '#', char split0 = '=', char split1 = ','):
		m_cCommentChar(comment), m_cSplitChar_kv(split0), m_cSplitChar_vv(split1)
	{
	}
	/*
	 * @brief read conf file and init m_mapConf
	 * */
	bool Init(const char *filename);
	/*
	 * @brief locate value
	 * */
	void GetValue(const string &firstkey, const string &secondkey, vector<string>&values);
	~ConfParse()
	{
	}
};
}
#endif

/*************************************************************************
    > File Name: confparse.cpp
    > Author: wangzhicheng
    > Mail: 2363702560@qq.com 
    > Created Time: Wed 12 Jul 2017 08:29:26 PM AWST
 ************************************************************************/
#include "confparse.h"
namespace confparse
{
void InnerKey::GetValue(const string &key, vector<string>&value)
{
	auto it = m_mapInner.find(key);
	if(it == m_mapInner.end()) return;
	set<string>&_value = it->second;
	value.clear();
	value.resize(_value.size());
	copy(begin(_value), end(_value), begin(value));
}
bool ConfParse::Init(const char *filename)
{
	if(!filename) return false;
	ifstream fstream(filename);
	if(!fstream) return false;
	string line;
	string newline;
	string lastfirstkey;
	string firstkey;
	string secondkey;
	string value;
	string::size_type size, pos;
	set<string>values;
	InnerKey innerKey;	
	m_mapConf.clear();
	while(!fstream.eof())
	{
		fstream >> line;
		if(line.empty()) continue;		// skip empty line
		if('#' == line[0]) continue;	// skip comment line
		size = line.size();
		// get [key]
		if(('[' == line[0]) && (']' == line[size - 1]))
		{
			firstkey.assign(line, 1, size - 2);
			if(lastfirstkey != firstkey)	// a new [] begin
			{
				m_mapConf.insert(make_pair(lastfirstkey, innerKey));		
				lastfirstkey = firstkey;
				innerKey.Clear();
			}
			continue;
		}
		// get inner key and values
		if((pos = line.find(m_cSplitChar_kv)) != string::npos)
		{
			secondkey.assign(line, 0, pos);
			newline.assign(line, pos + 1, size);
			for(auto it = begin(newline);it != end(newline);++it)
			{
				if(m_cSplitChar_vv == *it) *it = ' ';
			}
			istringstream ss(newline);
			values.clear();
			while(ss >> value) 
			{
				values.insert(value);
			}
			innerKey.Insert(secondkey, values);
		}
		line.clear();
	}
	if(!innerKey.Empty()) m_mapConf.insert(make_pair(firstkey, innerKey));		
	fstream.close();
	return !m_mapConf.empty();
}
void ConfParse::GetValue(const string &firstkey, const string &secondkey, vector<string>&values)
{
	values.clear();
	auto it = m_mapConf.find(firstkey);
	if(it == m_mapConf.end()) return;
	InnerKey &innerKey = it->second;
	innerKey.GetValue(secondkey, values);
}
}

TEST(ConfParse, TestInit)
{
	const char *path = "/home/wangzhicheng/C++/simple/confParse/example.conf";
	ConfParse confParse;
	EXPECT_EQ(true, confParse.Init(path));
}
TEST(ConfParse, TestGet)
{
	vector<string>values;
	const char *path = "/home/wangzhicheng/C++/simple/confParse/example.conf";
	ConfParse confParse;
	EXPECT_EQ(true, confParse.Init(path));
	confParse.GetValue("", "key0", values);
	EXPECT_EQ(1, values.size());
	EXPECT_EQ("v0", values[0]);
	confParse.GetValue("", "key1", values);
	EXPECT_EQ(2, values.size());
	EXPECT_EQ("v2", values[1]);
	confParse.GetValue("TT", "key3", values);
	EXPECT_EQ("v3", values[0]);
	EXPECT_EQ(1, values.size());

	path = "/home/wangzhicheng/C++/simple/confParse/example1.conf";
	EXPECT_EQ(true, confParse.Init(path));
	confParse.GetValue("", "key1", values);
	EXPECT_EQ("v2", values[1]);
	EXPECT_EQ(2, values.size());
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值