在做软件开发时,配置可少不了,我不建议你再写了,直接看如下的代码吧:
- #include <errno.h>
- #include <fstream>
- #include "util/tc_config.h"
- #include "util/tc_common.h"
-
- namespace tars
- {
-
- TC_ConfigDomain::TC_ConfigDomain(const string &sLine)
- {
- _name = TC_Common::trim(sLine);
- }
-
- TC_ConfigDomain::~TC_ConfigDomain()
- {
- destroy();
- }
-
- TC_ConfigDomain::TC_ConfigDomain(const TC_ConfigDomain &tcd)
- {
- (*this) = tcd;
- }
-
- TC_ConfigDomain& TC_ConfigDomain::operator=(const TC_ConfigDomain &tcd)
- {
- if(this != &tcd)
- {
- destroy();
-
- _name = tcd._name;
- _param = tcd._param;
- _key = tcd._key;
- _domain= tcd._domain;
- _line = tcd._line;
-
- const map<string, TC_ConfigDomain*> & m = tcd.getDomainMap();
- map<string, TC_ConfigDomain*>::const_iterator it = m.begin();
- while(it != m.end())
- {
- _subdomain[it->first] = it->second->clone();
- ++it;
- }
- }
- return *this;
- }
-
- TC_ConfigDomain::DomainPath TC_ConfigDomain::parseDomainName(const string& path, bool bWithParam)
- {
- TC_ConfigDomain::DomainPath dp;
-
- if(bWithParam)
- {
- string::size_type pos1 = path.find_first_of(TC_CONFIG_PARAM_BEGIN);
- if(pos1 == string::npos)
- {
- throw TC_Config_Exception("[TC_Config::parseDomainName] : param path '" + path + "' is invalid!" );
- }
-
- if(path[0] != TC_CONFIG_DOMAIN_SEP)
- {
- throw TC_Config_Exception("[TC_Config::parseDomainName] : param path '" + path + "' must start with '/'!" );
- }
-
- string::size_type pos2 = path.find_first_of(TC_CONFIG_PARAM_END);
- if(pos2 == string::npos)
- {
- throw TC_Config_Exception("[TC_Config::parseDomainName] : param path '" + path + "' is invalid!" );
- }
-
- dp._domains = TC_Common::sepstr<string>(path.substr(1, pos1-1), TC_Common::tostr(TC_CONFIG_DOMAIN_SEP));
- dp._param = path.substr(pos1+1, pos2 - pos1 - 1);
- }
- else
- {
- // if(path.length() <= 1 || path[0] != TC_CONFIG_DOMAIN_SEP)
- if(path[0] != TC_CONFIG_DOMAIN_SEP)
- {
- throw TC_Config_Exception("[TC_Config::parseDomainName] : param path '" + path + "' must start with '/'!" );
- }
-
- dp._domains = TC_Common::sepstr<string>(path.substr(1), TC_Common::tostr(TC_CONFIG_DOMAIN_SEP));
- }
-
- return dp;
- }
-
- TC_ConfigDomain* TC_ConfigDomain::addSubDomain(const string& name)
- {
- if(_subdomain.find(name) == _subdomain.end())
- {
- _domain.push_back(name);
-
- _subdomain[name] = new TC_ConfigDomain(name);
- }
- return _subdomain[name];
- }
-
- string TC_ConfigDomain::getParamValue(const string &name) const
- {
- map<string, string>::const_iterator it = _param.find(name);
- if( it == _param.end())
- {
- throw TC_ConfigNoParam_Exception("[TC_ConfigDomain::getParamValue] param '" + name + "' not exits!");
- }
-
- return it->second;
- }
-
- TC_ConfigDomain *TC_ConfigDomain::getSubTcConfigDomain(vector<string>::const_iterator itBegin, vector<string>::const_iterator itEnd)
- {
- if(itBegin == itEnd)
- {
- return this;
- }
-
- map<string, TC_ConfigDomain*>::const_iterator it = _subdomain.find(*itBegin);
-
- //根据匹配规则找不到匹配的子域
- if(it == _subdomain.end())
- {
- return NULL;
- }
-
- //继续在子域下搜索
- return it->second->getSubTcConfigDomain(itBegin + 1, itEnd);
- }
-
- const TC_ConfigDomain *TC_ConfigDomain::getSubTcConfigDomain(vector<string>::const_iterator itBegin, vector<string>::const_iterator itEnd) const
- {
- if(itBegin == itEnd)
- {
- return this;
- }
-
- map<string, TC_ConfigDomain*>::const_iterator it = _subdomain.find(*itBegin);
-
- //根据匹配规则找不到匹配的子域
- if(it == _subdomain.end())
- {
- return NULL;
- }
-
- //继续在子域下搜索
- return it->second->getSubTcConfigDomain(itBegin + 1, itEnd);
- }
-
- void TC_ConfigDomain::insertParamValue(const map<string, string> &m)
- {
- _param.insert(m.begin(), m.end());
-
- map<string, string>::const_iterator it = m.begin();
- while(it != m.end())
- {
- size_t i = 0;
- for(; i < _key.size(); i++)
- {
- if(_key[i] == it->first)
- {
- break;
- }
- }
-
- //没有该key, 则添加到最后
- if(i == _key.size())
- {
- _key.push_back(it->first);
- }
-
- ++it;
- }
- }
-
- void TC_ConfigDomain::setParamValue(const string &name, const string &value)
- {
- _param[name] = value;
-
- //如果key已经存在,则删除
- for(vector<string>::iterator it = _key.begin(); it != _key.end(); ++it)
- {
- if(*it == name)
- {
- _key.erase(it);
- break;
- }
- }
-
- _key.push_back(name);
- }
-
- void TC_ConfigDomain::setParamValue(const string &line)
- {
- if(line.empty())
- {
- return;
- }
-
- _line.push_back(line);
-
- string::size_type pos = 0;
- for(; pos <= line.length() - 1; pos++)
- {
- if (line[pos] == '=')
- {
- if(pos > 0 && line[pos-1] == '\\')
- {
- continue;
- }
-
- string name = parse(TC_Common::trim(line.substr(0, pos), " \r\n\t"));
-
- string value;
- if(pos < line.length() - 1)
- {
- value = parse(TC_Common::trim(line.substr(pos + 1), " \r\n\t"));
- }
-
- setParamValue(name, value);
- return;
- }
- }
-
- setParamValue(line, "");
- }
-
- string TC_ConfigDomain::parse(const string& s)
- {
- if(s.empty())
- {
- return "";
- }
-
- string param;
- string::size_type pos = 0;
- for(; pos <= s.length() - 1; pos++)
- {
- char c;
- if(s[pos] == '\\' && pos < s.length() - 1)
- {
- switch (s[pos+1])
- {
- case '\\':
- c = '\\';
- pos++;
- break;
- case 'r':
- c = '\r';
- pos++;
- break;
- case 'n':
- c = '\n';
- pos++;
- break;
- case 't':
- c = '\t';
- pos++;
- break;
- case '=':
- c = '=';
- pos++;
- break;
- default:
- throw TC_Config_Exception("[TC_ConfigDomain::parse] '" + s + "' is invalid, '" + TC_Common::tostr(s[pos]) + TC_Common::tostr(s[pos+1]) + "' couldn't be parse!" );
- }
-
- param += c;
- }
- else if (s[pos] == '\\')
- {
- throw TC_Config_Exception("[TC_ConfigDomain::parse] '" + s + "' is invalid, '" + TC_Common::tostr(s[pos]) + "' couldn't be parse!" );
- }
- else
- {
- param += s[pos];
- }
- }
-
- return param;
- }
-
- string TC_ConfigDomain::reverse_parse(const string &s)
- {
- if(s.empty())
- {
- return "";
- }
-
- string param;
- string::size_type pos = 0;
- for(; pos <= s.length() - 1; pos++)
- {
- string c;
- switch (s[pos])
- {
- case '\\':
- param += "\\\\";
- break;
- case '\r':
- param += "\\r";
- break;
- case '\n':
- param += "\\n";
- break;
- case '\t':
- param += "\\t";
- break;
- break;
- case '=':
- param += "\\=";
- break;
- case '<':
- case '>':
- throw TC_Config_Exception("[TC_ConfigDomain::reverse_parse] '" + s + "' is invalid, couldn't be parse!" );
- default:
- param += s[pos];
- }
- }
-
- return param;
- }
-
- string TC_ConfigDomain::getName() const
- {
- return _name;
- }
-
- void TC_ConfigDomain::setName(const string& name)
- {
- _name = name;
- }
-
- vector<string> TC_ConfigDomain::getKey() const
- {
- return _key;
- }
-
- vector<string> TC_ConfigDomain::getLine() const
- {
- return _line;
- }
-
- vector<string> TC_ConfigDomain::getSubDomain() const
- {
- return _domain;
- }
-
- void TC_ConfigDomain::destroy()
- {
- _param.clear();
- _key.clear();
- _line.clear();
- _domain.clear();
-
- map<string, TC_ConfigDomain*>::iterator it = _subdomain.begin();
- while(it != _subdomain.end())
- {
- delete it->second;
- ++it;
- }
-
- _subdomain.clear();
- }
-
- string TC_ConfigDomain::tostr(int i) const
- {
- string sTab;
- for(int k = 0; k < i; ++k)
- {
- sTab += "\t";
- }
-
- ostringstream buf;
-
- buf << sTab << "<" << reverse_parse(_name) << ">" << endl;;
-
- for(size_t n = 0; n < _key.size(); n++)
- {
- map<string, string>::const_iterator it = _param.find(_key[n]);
-
- assert(it != _param.end());
-
- //值为空, 则不打印出=
- if(it->second.empty())
- {
- buf << "\t" << sTab << reverse_parse(_key[n]) << endl;
- }
- else
- {
- buf << "\t" << sTab << reverse_parse(_key[n]) << "=" << reverse_parse(it->second) << endl;
- }
- }
-
- ++i;
-
- for(size_t n = 0; n < _domain.size(); n++)
- {
- map<string, TC_ConfigDomain*>::const_iterator itm = _subdomain.find(_domain[n]);
-
- assert(itm != _subdomain.end());
-
- buf << itm->second->tostr(i);
- }
-
-
- buf << sTab << "</" << reverse_parse(_name) << ">" << endl;
-
- return buf.str();
- }
-
- /********************************************************************/
- /* TC_Config implement */
- /********************************************************************/
-
- TC_Config::TC_Config() : _root("")
- {
- }
-
- TC_Config::TC_Config(const TC_Config &tc)
- : _root(tc._root)
- {
-
- }
-
- TC_Config& TC_Config::operator=(const TC_Config &tc)
- {
- if(this != &tc)
- {
- _root = tc._root;
- }
-
- return *this;
- }
-
- void TC_Config::parse(istream &is)
- {
- _root.destroy();
-
- stack<TC_ConfigDomain*> stkTcCnfDomain;
- stkTcCnfDomain.push(&_root);
-
- string line;
- while(getline(is, line))
- {
- line = TC_Common::trim(line, " \r\n\t");
-
- if(line.length() == 0)
- {
- continue;
- }
-
- if(line[0] == '#')
- {
- continue;
- }
- else if(line[0] == '<')
- {
- string::size_type posl = line.find_first_of('>');
-
- if(posl == string::npos)
- {
- throw TC_Config_Exception("[TC_Config::parse]:parse error! line : " + line);
- }
-
- if(line[1] == '/')
- {
- string sName(line.substr(2, (posl - 2)));
-
- if(stkTcCnfDomain.size() <= 0)
- {
- throw TC_Config_Exception("[TC_Config::parse]:parse error! <" + sName + "> hasn't matched domain.");
- }
-
- if(stkTcCnfDomain.top()->getName() != sName)
- {
- throw TC_Config_Exception("[TC_Config::parse]:parse error! <" + stkTcCnfDomain.top()->getName() + "> hasn't match <" + sName +">.");
- }
-
- //弹出
- stkTcCnfDomain.pop();
- }
- else
- {
- string name(line.substr(1, posl - 1));
-
- stkTcCnfDomain.push(stkTcCnfDomain.top()->addSubDomain(name));
- }
- }
- else
- {
- stkTcCnfDomain.top()->setParamValue(line);
- }
- }
-
- if(stkTcCnfDomain.size() != 1)
- {
- throw TC_Config_Exception("[TC_Config::parse]:parse error : hasn't match");
- }
- }
-
- void TC_Config::parseFile(const string &sFileName)
- {
- if(sFileName.length() == 0)
- {
- throw TC_Config_Exception("[TC_Config::parseFile]:file name is empty");
- }
-
- ifstream ff;
- ff.open(sFileName.c_str());
- if (!ff)
- {
- throw TC_Config_Exception("[TC_Config::parseFile]:fopen fail: " + sFileName, errno);
- }
-
- parse(ff);
- }
-
- void TC_Config::parseString(const string& buffer)
- {
- istringstream iss;
- iss.str(buffer);
-
- parse(iss);
- }
-
- string TC_Config::operator[](const string &path)
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(path, true);
-
- TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain == NULL)
- {
- throw TC_ConfigNoParam_Exception("[TC_Config::operator[]] path '" + path + "' not exits!");
- }
-
- return pTcConfigDomain->getParamValue(dp._param);
- }
-
- string TC_Config::get(const string &sName, const string &sDefault) const
- {
- try
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(sName, true);
-
- const TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain == NULL)
- {
- throw TC_ConfigNoParam_Exception("[TC_Config::get] path '" + sName + "' not exits!");
- }
-
- return pTcConfigDomain->getParamValue(dp._param);
- }
- catch ( TC_ConfigNoParam_Exception &ex )
- {
- return sDefault;
- }
- }
-
- bool TC_Config::getDomainMap(const string &path, map<string, string> &m) const
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(path, false);
-
- const TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain == NULL)
- {
- return false;
- }
-
- m = pTcConfigDomain->getParamMap();
-
- return true;
- }
-
- map<string, string> TC_Config::getDomainMap(const string &path) const
- {
- map<string, string> m;
-
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(path, false);
-
- const TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain != NULL)
- {
- m = pTcConfigDomain->getParamMap();
- }
-
- return m;
- }
-
- vector<string> TC_Config::getDomainKey(const string &path) const
- {
- vector<string> v;
-
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(path, false);
-
- const TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain != NULL)
- {
- v = pTcConfigDomain->getKey();
- }
-
- return v;
- }
-
- vector<string> TC_Config::getDomainLine(const string &path) const
- {
- vector<string> v;
-
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(path, false);
-
- const TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain != NULL)
- {
- v = pTcConfigDomain->getLine();
- }
-
- return v;
- }
-
- bool TC_Config::getDomainVector(const string &path, vector<string> &vtDomains) const
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(path, false);
-
- //根域, 特殊处理
- if(dp._domains.empty())
- {
- vtDomains = _root.getSubDomain();
- return !vtDomains.empty();
- }
-
- const TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain == NULL)
- {
- return false;
- }
-
- vtDomains = pTcConfigDomain->getSubDomain();
-
- return true;
- }
-
- vector<string> TC_Config::getDomainVector(const string &path) const
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(path, false);
-
- //根域, 特殊处理
- if(dp._domains.empty())
- {
- return _root.getSubDomain();
- }
-
- const TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain == NULL)
- {
- return vector<string>();
- }
-
- return pTcConfigDomain->getSubDomain();
- }
-
-
- TC_ConfigDomain *TC_Config::newTcConfigDomain(const string &sName)
- {
- return new TC_ConfigDomain(sName);
- }
-
- TC_ConfigDomain *TC_Config::searchTcConfigDomain(const vector<string>& domains)
- {
- return _root.getSubTcConfigDomain(domains.begin(), domains.end());
- }
-
- const TC_ConfigDomain *TC_Config::searchTcConfigDomain(const vector<string>& domains) const
- {
- return _root.getSubTcConfigDomain(domains.begin(), domains.end());
- }
-
- int TC_Config::insertDomain(const string &sCurDomain, const string &sAddDomain, bool bCreate)
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(sCurDomain, false);
-
- TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain == NULL)
- {
- if(bCreate)
- {
- pTcConfigDomain = &_root;
-
- for(size_t i = 0; i < dp._domains.size(); i++)
- {
- pTcConfigDomain = pTcConfigDomain->addSubDomain(dp._domains[i]);
- }
- }
- else
- {
- return -1;
- }
- }
-
- pTcConfigDomain->addSubDomain(sAddDomain);
-
- return 0;
- }
-
- int TC_Config::insertDomainParam(const string &sCurDomain, const map<string, string> &m, bool bCreate)
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(sCurDomain, false);
-
- TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
-
- if(pTcConfigDomain == NULL)
- {
- if(bCreate)
- {
- pTcConfigDomain = &_root;
-
- for(size_t i = 0; i < dp._domains.size(); i++)
- {
- pTcConfigDomain = pTcConfigDomain->addSubDomain(dp._domains[i]);
- }
- }
- else
- {
- return -1;
- }
- }
-
- pTcConfigDomain->insertParamValue(m);
-
- return 0;
- }
-
- string TC_Config::tostr() const
- {
- string buffer;
-
- map<string, TC_ConfigDomain*> msd = _root.getDomainMap();
- map<string, TC_ConfigDomain*>::const_iterator it = msd.begin();
- while (it != msd.end())
- {
- buffer += it->second->tostr(0);
- ++it;
- }
-
- return buffer;
- }
-
- void TC_Config::joinConfig(const TC_Config &cf, bool bUpdate)
- {
- string buffer;
- if(bUpdate)
- {
- buffer = tostr() + cf.tostr();
- }
- else
- {
- buffer = cf.tostr() + tostr();
- }
- parseString(buffer);
- }
-
- }