C++ implements the generic parameter resolution class example
- 2020-04-02 02:11:04
- OfStack
main.cpp
#include <iostream>
#include <getopt.h>
#include "parsingargs.h"
#include <string.h>
using namespace std;
int main(int argc, char * argv[])
{
//string tmpPara = "-p "4567" --out 1.log "; //ok
//string tmpPara = "xxxx -p "4567" --out 1.log ";//ok
//string tmpPara = "-p "4567" --out 1.log 2.log"; //ok
string tmpPara = "";
for(int i=1;i <argc; i++)
{
cout << i << "=" << argv[i] <<"---"<< endl;
if(strlen(argv[i]) == 0) //Dealing with empty strings
{
cout << "find NULL" << endl;
tmpPara += char(31);
}
else
{
tmpPara += argv[i];
}
tmpPara += " ";
}
std::map<std::string, std::vector<std::string> > result;
ParsingArgs pa;
pa.AddArgType('l',"getlist", ParsingArgs::NO_VALUE);
pa.AddArgType('p',"getuser", ParsingArgs::MAYBE_VALUE);
pa.AddArgType('o',"outFile", ParsingArgs::MUST_VALUE);
bool bExit = false;
do
{
result.clear();
cout << "input is:" << tmpPara << "---size = " << tmpPara.size()<< endl;
std::string errPos;
int iRet = pa.Parse(tmpPara,result, errPos);
if(0>iRet)
{
cout << " Parameter error " << iRet << errPos << endl;
}
else
{
map<std::string, std::vector<std::string> >::iterator it = result.begin();
for(; it != result.end(); ++it)
{
cout << "key=" << it->first<<endl;
for(int i=0; i<it->second.size(); ++i)
{
cout << " value =" << it->second[i] << "------" << endl;
}
}
}
string str;
cout << ">>> ";
getline(cin, tmpPara);
if(0 == tmpPara.compare("exit"))
{
bExit = true;
}
}while(!bExit);
return 0;
}
parsingargs.h
#ifndef PARSINGARGS_H
#define PARSINGARGS_H
/* purpose @ To parse the input parameters, pass first AddArgType Parameters will be required and allowed key Add to the decision list
* through Parse In the result Returns the result of key For legal key . vecotr Is the parameter list
* Parameter lists support the removal of quotes before and after parameters and the escape of quotes and
*
* Special legal field:
* format Actual stored value
* \value" value"
* "\value"" value"
*
* Notes:
* 1 , the parameters in the input parameter list are separated by Spaces
* 2 , - After the single character keyword, -- Followed by a long string keyword
* 3 , keyword can not be repeated, long and short keywords can not appear in the parameter list at the same time, otherwise Parse The function prompts for an argument error
*
* Usage:
* ParsingArgs pa;
* pa.AddArgType('l',"getlist", ParsingArgs::NO_VALUE); //The NO_VALUE keyword cannot be followed by an argument
* pa.AddArgType('p',"getuser", ParsingArgs::MAYBE_VALUE); //There may be a keyword after the MAYBE_VALUE keyword
* pa.AddArgType('o',"outFile", ParsingArgs::MUST_VALUE); //The MUST_VALUE keyword must be followed by an argument
* std::map<std::string, std::vector<std::string> > result;
* int iRet = pa.Parse(tmpPara,result); //Result stores a sequence of related values with the input keyword as the key
*
* date @ 2014.02.19
* author @ haibin.wang
*
*/
#include <map>
#include <vector>
#include <string>
class ParsingArgs
{
public:
ParsingArgs();
~ParsingArgs();
enum KeyFlag{ INVALID_KEY=-1, NO_VALUE, MAYBE_VALUE, MUST_VALUE};
bool AddArgType(const char shortName, const char * longName = NULL, KeyFlag flag=NO_VALUE);
int Parse(const std::string & paras, std::map<std::string, std::vector<std::string> > & result, std::string &errPos);
private:
KeyFlag GetKeyFlag(std::string &key);
void RemoveKeyFlag(std::string & paras);
bool GetWord(std::string & Paras, std::string & word);
bool IsDuplicateKey(const std::string &key, const std::map<std::string, std::vector<std::string> > & result);
struct Option
{
std::string m_longName;
char m_shortName;
KeyFlag m_flag;
};
std::vector<Option> m_args; //Parameter information list
};
#endif
parsingargs.cpp
#include "parsingargs.h"
#include <list>
ParsingArgs::ParsingArgs()
{
}
ParsingArgs::~ParsingArgs()
{
}
bool ParsingArgs::AddArgType(char shortName, const char * longName, KeyFlag flag)
{
if(NULL == longName && 0 == shortName)
{
return false;
}
Option tmp;
tmp.m_longName = longName;
tmp.m_shortName = shortName;
tmp.m_flag = flag;
m_args.push_back(tmp);
return true;
}
ParsingArgs::KeyFlag ParsingArgs::GetKeyFlag(std::string &key) //Returns the flag,
{
for(int i=0; i<m_args.size(); ++i)
{
std::string shortName = "-";
std::string longName = "--";
shortName += m_args[i].m_shortName;
longName += m_args[i].m_longName;
if( 0 == key.compare(shortName) ||
(0==key.compare(longName))
)
{
RemoveKeyFlag(key);
return m_args[i].m_flag;
}
}
return INVALID_KEY;
}
void ParsingArgs::RemoveKeyFlag(std::string & word)
{
if(word.size()>=2)
{
if(word[1] == '-')
{
word.erase(1,1);
}
if(word[0] == '-')
{
word.erase(0,1);
}
}
}
bool ParsingArgs::GetWord(std::string & Paras, std::string & word)
{
size_t iNotSpacePos = Paras.find_first_not_of(' ',0);//Find the first non-space character position
if(iNotSpacePos == std::string::npos)
{
Paras.clear();
word.clear();
return true;
}
int length = Paras.size();
std::list<char> specialChar;
int islashPos = -1;
for(int i=iNotSpacePos; i<length; i++)
{
char cur=Paras[i];
bool bOk = false;
switch(cur)
{
case ' ':
if(specialChar.empty())
{
if(i!=(length-1))
{
Paras = std::string(Paras, i+1, length-i-1);
}
else
{//The last one is a space
Paras.clear();
}
bOk = true;
}
else
{
if(specialChar.back() == '\')
{
specialChar.pop_back();
}
word.append(1,cur);
}
break;
case '"':
if(specialChar.empty())
{
specialChar.push_back(cur);
}
else if(specialChar.back() == cur)
{ //Find the matching parentheses
specialChar.pop_back();
}
else if(specialChar.back() == '\')
{
word.append(1,cur);
specialChar.pop_back();
}
else
{
word.clear();
return false;
}
break;
case '\':
if(specialChar.empty())
{
specialChar.push_back(cur);
islashPos = i;
}
else if(specialChar.back() == '"')
{
if(i<(length-1))
{
if('"'==Paras[i+1] || '\'==Paras[i+1])
{
specialChar.push_back(cur);
}
else
{
word.append(1,cur);
}
}
else
{
word.clear();
return false;
}
}
else if('\' == specialChar.back())
{
word.append(1,cur);
specialChar.pop_back();
}
else
{
word.clear();
return false;
}
break;
default:
word.append(1,Paras[i]);
if(i==(length-1))
{
bOk = true;
Paras.clear();
}
break;
}
if(bOk)
{
return true;
}
}//for end
if(specialChar.empty())
{
Paras.clear();
return true;
}
else
{
return false;
}
}
bool ParsingArgs::IsDuplicateKey(const std::string &key, const std::map<std::string, std::vector<std::string> > & result)
{
if(result.find(key) != result.end())
{
return true; //Keyword repetition
}
for(int i=0; i<m_args.size(); ++i)
{
if( (key.compare(m_args[i].m_longName) == 0 && result.find(std::string(1, m_args[i].m_shortName)) != result.end())
|| (key.compare(std::string(1, m_args[i].m_shortName)) == 0 && result.find(m_args[i].m_longName) != result.end())
)
{
return true;
}
}
return false;
}
int ParsingArgs::Parse(const std::string & Paras, std::map<std::string, std::vector<std::string> > & result, std::string &errPos)
{
std::string tmpString = Paras;
KeyFlag keyFlag = INVALID_KEY; //Parameter identification
std::string sKey = ""; //Key the keyword
bool bFindValue = false; //Is there a value already
while(!tmpString.empty())
{
std::string word = "";
bool bRet = GetWord(tmpString, word);
if(bRet == false)
{
errPos = tmpString;
return -4;//Parameter parsing error
}
else
{
KeyFlag tmpFlag = GetKeyFlag(word);
if(IsDuplicateKey(word, result))
{
errPos = tmpString;
return -5;
}
if(tmpFlag != INVALID_KEY)
{
if(tmpFlag == MUST_VALUE && keyFlag == MUST_VALUE && !bFindValue)
{
errPos = tmpString;
return -3;
}
keyFlag = tmpFlag;
std::vector<std::string> tmp;
result[word] = tmp;
sKey = word;
bFindValue = false;
}
else
{
switch(keyFlag)
{
case MAYBE_VALUE:
case MUST_VALUE:
{
std::map<std::string, std::vector<std::string> >::iterator it = result.find(sKey);
if(it != result.end())
{
it->second.push_back(word);
bFindValue = true;
}
else
{
errPos = tmpString;
return -1;//No associated key was found
}
}
break;
case NO_VALUE:
errPos = tmpString;
return -2; //Options that cannot have arguments have arguments
default:
errPos = tmpString;
return -1;//Parameter error
}//switch end
}
}
}//while end
return 0;
}