#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());
}
confparse
最新推荐文章于 2020-09-10 11:57:11 发布