123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832 |
- /**
- * Tencent is pleased to support the open source community by making Tars available.
- *
- * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
- *
- * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * https://opensource.org/licenses/BSD-3-Clause
- *
- * Unless required by applicable law or agreed to in writing, software distributed
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
- #include <cerrno>
- #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)
- {
- for(auto e : m)
- {
- _param[e.first] = e.second;
- }
- 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;
- }
- }
- // also need parse
- string name = parse(TC_Common::trim(line, " \r\n\t"));
- setParamValue(name, "");
- }
- 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;
- 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 += " ";
- }
- 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 << " " << sTab << reverse_parse(_key[n]) << endl;
- }
- else
- {
- buf << " " << 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_EXCEPTION_SYSCODE(TC_Config_Exception, "[TC_Config::parseFile]:fopen fail: " + sFileName);
- // throw TC_Config_Exception("[TC_Config::parseFile]:fopen fail: " + sFileName, TC_Exception::getSystemCode());
- }
- parse(ff);
- }
- void TC_Config::parseString(const string& buffer)
- {
- istringstream iss;
- iss.str(buffer);
- parse(iss);
- }
- string TC_Config::operator[](const string &path) const
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(path, true);
- const 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)
- {
- return sDefault;
- // throw TC_ConfigNoParam_Exception("[TC_Config::get] path '" + sName + "' not exits!");
- }
- return pTcConfigDomain->getParamValue(dp._param);
- }
- catch ( TC_ConfigNoParam_Exception &ex )
- {
- return sDefault;
- }
- }
- void TC_Config::set(const string &sName, const string &value)
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(sName, true);
- map<string, string> v;
- v[dp._param] = value;
- TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
- if(pTcConfigDomain == NULL)
- {
- pTcConfigDomain = &_root;
- for(size_t i = 0; i < dp._domains.size(); i++)
- {
- pTcConfigDomain = pTcConfigDomain->addSubDomain(dp._domains[i]);
- }
- }
- pTcConfigDomain->insertParamValue(v);
- }
- 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::hasDomainVector(const string &path) const
- {
- TC_ConfigDomain::DomainPath dp = TC_ConfigDomain::parseDomainName(path, false);
- //根域, 特殊处理
- if(dp._domains.empty())
- {
- return !_root.getSubDomain().empty();
- }
- const TC_ConfigDomain *pTcConfigDomain = searchTcConfigDomain(dp._domains);
- if(pTcConfigDomain == NULL)
- {
- return false;
- }
- return true;
- }
- 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);
- }
- }
|