您的位置:首页 > 编程语言 > C语言/C++

命令行解析器

2015-06-09 14:45 375 查看
本文由 @lonelyrains 出品,转载请注明出处。 
文章链接: http://blog.csdn.net/lonelyrains/article/details/46426645

opencv2.4.8  core.hpp 

/*!
"\nThe CommandLineParser class is designed for command line arguments parsing\n"
"Keys map: \n"
"Before you start to work with CommandLineParser you have to create a map for keys.\n"
"    It will look like this\n"
"    const char* keys =\n"
"    {\n"
"        {    s|  string|  123asd |string parameter}\n"
"        {    d|  digit |  100    |digit parameter }\n"
"        {    c|noCamera|false    |without camera  }\n"
"        {    1|        |some text|help            }\n"
"        {    2|        |333      |another help    }\n"
"    };\n"
"Usage syntax: \n"
"    \"{\" - start of parameter string.\n"
"    \"}\" - end of parameter string\n"
"    \"|\" - separator between short name, full name, default value and help\n"
"Supported syntax: \n"
"    --key1=arg1  <If a key with '--' must has an argument\n"
"                  you have to assign it through '=' sign.> \n"
"<If the key with '--' doesn't have any argument, it means that it is a bool key>\n"
"    -key2=arg2   <If a key with '-' must has an argument \n"
"                  you have to assign it through '=' sign.> \n"
"If the key with '-' doesn't have any argument, it means that it is a bool key\n"
"    key3                 <This key can't has any parameter> \n"
"Usage: \n"
"      Imagine that the input parameters are next:\n"
"                -s=string_value --digit=250 --noCamera lena.jpg 10000\n"
"    CommandLineParser parser(argc, argv, keys) - create a parser object\n"
"    parser.get<string>(\"s\" or \"string\") will return you first parameter value\n"
"    parser.get<string>(\"s\", false or \"string\", false) will return you first parameter value\n"
"                                                                without spaces in end and begin\n"
"    parser.get<int>(\"d\" or \"digit\") will return you second parameter value.\n"
"                    It also works with 'unsigned int', 'double', and 'float' types>\n"
"    parser.get<bool>(\"c\" or \"noCamera\") will return you true .\n"
"                                If you enter this key in commandline>\n"
"                                It return you false otherwise.\n"
"    parser.get<string>(\"1\") will return you the first argument without parameter (lena.jpg) \n"
"    parser.get<int>(\"2\") will return you the second argument without parameter (10000)\n"
"                          It also works with 'unsigned int', 'double', and 'float' types \n"
*/
class CV_EXPORTS CommandLineParser
{
public:

//! the default constructor
CommandLineParser(int argc, const char* const argv[], const char* key_map);

//! get parameter, you can choose: delete spaces in end and begin or not
template<typename _Tp>
_Tp get(const std::string& name, bool space_delete=true)
{
if (!has(name))
{
return _Tp();
}
std::string str = getString(name);
return analyzeValue<_Tp>(str, space_delete);
}

//! print short name, full name, current value and help for all params
void printParams();

protected:
std::map<std::string, std::vector<std::string> > data;
std::string getString(const std::string& name);

bool has(const std::string& keys);

template<typename _Tp>
_Tp analyzeValue(const std::string& str, bool space_delete=false);

template<typename _Tp>
static _Tp getData(const std::string& str)
{
_Tp res = _Tp();
std::stringstream s1(str);
s1 >> res;
return res;
}

template<typename _Tp>
_Tp fromStringNumber(const std::string& str);//the default conversion function for numbers

};

template<> CV_EXPORTS
bool CommandLineParser::get<bool>(const std::string& name, bool space_delete);

template<> CV_EXPORTS
std::string CommandLineParser::analyzeValue<std::string>(const std::string& str, bool space_delete);

template<> CV_EXPORTS
int CommandLineParser::analyzeValue<int>(const std::string& str, bool space_delete);

template<> CV_EXPORTS
unsigned int CommandLineParser::analyzeValue<unsigned int>(const std::string& str, bool space_delete);

template<> CV_EXPORTS
uint64 CommandLineParser::analyzeValue<uint64>(const std::string& str, bool space_delete);

template<> CV_EXPORTS
float CommandLineParser::analyzeValue<float>(const std::string& str, bool space_delete);

template<> CV_EXPORTS
double CommandLineParser::analyzeValue<double>(const std::string& str, bool space_delete);


cmdparser.cpp

#include "precomp.hpp"

#include <iostream>
#include <iomanip>

using namespace std;
using namespace cv;

namespace {
void helpParser()
{
printf("\nThe CommandLineParser class is designed for command line arguments parsing\n"
"Keys map: \n"
"Before you start to work with CommandLineParser you have to create a map for keys.\n"
"    It will look like this\n"
"    const char* keys =\n"
"    {\n"
"        {    s|  string|  123asd |string parameter}\n"
"        {    d|  digit |  100    |digit parameter }\n"
"        {    c|noCamera|false    |without camera  }\n"
"        {    1|        |some text|help            }\n"
"        {    2|        |333      |another help    }\n"
"    };\n"
"Usage syntax: \n"
"    \"{\" - start of parameter string.\n"
"    \"}\" - end of parameter string\n"
"    \"|\" - separator between short name, full name, default value and help\n"
"Supported syntax: \n"
"    --key1=arg1  <If a key with '--' must has an argument\n"
"                  you have to assign it through '=' sign.> \n"
"<If the key with '--' doesn't have any argument, it means that it is a bool key>\n"
"    -key2=arg2   <If a key with '-' must has an argument \n"
"                  you have to assign it through '=' sign.> \n"
"If the key with '-' doesn't have any argument, it means that it is a bool key\n"
"    key3                 <This key can't has any parameter> \n"
"Usage: \n"
"      Imagine that the input parameters are next:\n"
"                -s=string_value --digit=250 --noCamera lena.jpg 10000\n"
"    CommandLineParser parser(argc, argv, keys) - create a parser object\n"
"    parser.get<string>(\"s\" or \"string\") will return you first parameter value\n"
"    parser.get<string>(\"s\", false or \"string\", false) will return you first parameter value\n"
"                                                                without spaces in end and begin\n"
"    parser.get<int>(\"d\" or \"digit\") will return you second parameter value.\n"
"                    It also works with 'unsigned int', 'double', and 'float' types>\n"
"    parser.get<bool>(\"c\" or \"noCamera\") will return you true .\n"
"                                If you enter this key in commandline>\n"
"                                It return you false otherwise.\n"
"    parser.get<string>(\"1\") will return you the first argument without parameter (lena.jpg) \n"
"    parser.get<int>(\"2\") will return you the second argument without parameter (10000)\n"
"                          It also works with 'unsigned int', 'double', and 'float' types \n"
);
}

vector<string> split_string(const string& str, const string& delimiters)
{
vector<string> res;

string split_str = str;
size_t pos_delim = split_str.find(delimiters);

while ( pos_delim != string::npos)
{
if (pos_delim == 0)
{
res.push_back("");
split_str.erase(0, 1);
}
else
{
res.push_back(split_str.substr(0, pos_delim));
split_str.erase(0, pos_delim + 1);
}

pos_delim = split_str.find(delimiters);
}

res.push_back(split_str);

return res;
}

string del_space(string name)
{
while ((name.find_first_of(' ') == 0)  && (name.length() > 0))
name.erase(0, 1);

while ((name.find_last_of(' ') == (name.length() - 1)) && (name.length() > 0))
name.erase(name.end() - 1, name.end());

return name;
}

}//namespace

static bool keyIsNumber(const std::string & option, size_t start)
{
bool isNumber = true;
size_t end = option.find_first_of('=', start);
end = option.npos == end ? option.length() : end;

for ( ; start < end; ++start)
if (!isdigit(option[start]))
{
isNumber = false;
break;
}

return isNumber;
}

CommandLineParser::CommandLineParser(int argc, const char* const argv[], const char* keys)
{
std::string keys_buffer;
std::string values_buffer;
std::string buffer;
std::string curName;
std::vector<string> keysVector;
std::vector<string> paramVector;
std::map<std::string, std::vector<std::string> >::iterator it;
size_t flagPosition;
int currentIndex = 1;
//bool isFound = false;
bool withNoKey = false;
bool hasValueThroughEq = false;

keys_buffer = keys;
while (!keys_buffer.empty())
{

flagPosition = keys_buffer.find_first_of('}');
flagPosition++;
buffer = keys_buffer.substr(0, flagPosition);
keys_buffer.erase(0, flagPosition);

flagPosition = buffer.find('{');
if (flagPosition != buffer.npos)
buffer.erase(flagPosition, (flagPosition + 1));

flagPosition = buffer.find('}');
if (flagPosition != buffer.npos)
buffer.erase(flagPosition);

paramVector = split_string(buffer, "|");
while (paramVector.size() < 4) paramVector.push_back("");

buffer = paramVector[0];
buffer += '|' + paramVector[1];

//if (buffer == "") CV_ERROR(CV_StsBadArg, "In CommandLineParser need set short and full name");

paramVector.erase(paramVector.begin(), paramVector.begin() + 2);
data[buffer] = paramVector;
}

buffer.clear();
keys_buffer.clear();
paramVector.clear();
for (int i = 1; i < argc; i++)
{
if (!argv[i])
break;
curName = argv[i];

size_t nondash = curName.find_first_not_of("-");
if (nondash == 0 || nondash == curName.npos || keyIsNumber(curName, nondash))
withNoKey = true;
else
curName.erase(0, nondash);

if (curName.find('=') != curName.npos)
{
hasValueThroughEq = true;
buffer = curName;
curName.erase(curName.find('='));
buffer.erase(0, (buffer.find('=') + 1));
}

values_buffer = del_space(values_buffer);

for(it = data.begin(); it != data.end(); it++)
{
keys_buffer = it->first;
keysVector = split_string(keys_buffer, "|");

for (size_t j = 0; j < keysVector.size(); j++) keysVector[j] = del_space(keysVector[j]);

values_buffer = it->second[0];
if (((curName == keysVector[0]) || (curName == keysVector[1])) && hasValueThroughEq)
{
it->second[0] = buffer;
//isFound = true;
break;
}

if (!hasValueThroughEq && ((curName == keysVector[0]) || (curName == keysVector[1]))
&& (
values_buffer.find("false") != values_buffer.npos ||
values_buffer == ""
))
{
it->second[0] = "true";
//isFound = true;
break;
}

if (!hasValueThroughEq && (values_buffer.find("false") == values_buffer.npos) &&
((curName == keysVector[0]) || (curName == keysVector[1])))
{
it->second[0] = argv[++i];
//isFound = true;
break;
}

if (withNoKey)
{
std::string noKeyStr = it->first;
if(atoi(noKeyStr.c_str()) == currentIndex)
{
it->second[0] = curName;
currentIndex++;
//isFound = true;
break;
}
}
}

withNoKey = false;
hasValueThroughEq = false;
//isFound = false;
}
}

bool CommandLineParser::has(const std::string& keys)
{
std::map<std::string, std::vector<std::string> >::iterator it;
std::vector<string> keysVector;

for(it = data.begin(); it != data.end(); it++)
{
keysVector = split_string(it->first, "|");
for (size_t i = 0; i < keysVector.size(); i++) keysVector[i] = del_space(keysVector[i]);

if (keysVector.size() == 1) keysVector.push_back("");

if ((del_space(keys).compare(keysVector[0]) == 0) ||
(del_space(keys).compare(keysVector[1]) == 0))
return true;
}

return false;
}

std::string CommandLineParser::getString(const std::string& keys)
{
std::map<std::string, std::vector<std::string> >::iterator it;
std::vector<string> valueVector;

for(it = data.begin(); it != data.end(); it++)
{
valueVector = split_string(it->first, "|");
for (size_t i = 0; i < valueVector.size(); i++) valueVector[i] = del_space(valueVector[i]);

if (valueVector.size() == 1) valueVector.push_back("");

if ((del_space(keys).compare(valueVector[0]) == 0) ||
(del_space(keys).compare(valueVector[1]) == 0))
return it->second[0];
}
return string();
}

template<typename _Tp>
_Tp CommandLineParser::fromStringNumber(const std::string& str)//the default conversion function for numbers
{
return getData<_Tp>(str);
}

void CommandLineParser::printParams()
{
int col_p = 30;
int col_d = 50;

std::map<std::string, std::vector<std::string> >::iterator it;
std::vector<string> keysVector;
std::string buf;
for(it = data.begin(); it != data.end(); it++)
{
keysVector = split_string(it->first, "|");
for (size_t i = 0; i < keysVector.size(); i++) keysVector[i] = del_space(keysVector[i]);

cout << "  ";
buf = "";
if (keysVector[0] != "")
{
buf = "-" + keysVector[0];
if (keysVector[1] != "") buf += ", --" + keysVector[1];
}
else if (keysVector[1] != "") buf += "--" + keysVector[1];
if (del_space(it->second[0]) != "") buf += "=[" + del_space(it->second[0]) + "]";

cout << setw(col_p-2) << left << buf;

if ((int)buf.length() > col_p-2)
{
cout << endl << "  ";
cout << setw(col_p-2) << left << " ";
}

buf = "";
if (del_space(it->second[1]) != "") buf += del_space(it->second[1]);

for(;;)
{
bool tr = ((int)buf.length() > col_d-2) ? true: false;
std::string::size_type pos = 0;

if (tr)
{
pos = buf.find_first_of(' ');
for(;;)
{
if (buf.find_first_of(' ', pos + 1 ) < (std::string::size_type)(col_d-2) &&
buf.find_first_of(' ', pos + 1 ) != std::string::npos)
pos = buf.find_first_of(' ', pos + 1);
else
break;
}
pos++;
cout << setw(col_d-2) << left << buf.substr(0, pos) << endl;
}
else
{
cout << setw(col_d-2) << left << buf<< endl;
break;
}

buf.erase(0, pos);
cout << "  ";
cout << setw(col_p-2) << left << " ";
}
}
}

template<>
bool CommandLineParser::get<bool>(const std::string& name, bool space_delete)
{
std::string str_buf = getString(name);

if (space_delete && str_buf != "")
{
str_buf = del_space(str_buf);
}

if (str_buf == "true")
return true;

return false;
}
template<>
std::string CommandLineParser::analyzeValue<std::string>(const std::string& str, bool space_delete)
{
if (space_delete)
{
return del_space(str);
}
return str;
}

template<>
int CommandLineParser::analyzeValue<int>(const std::string& str, bool /*space_delete*/)
{
return fromStringNumber<int>(str);
}

template<>
unsigned int CommandLineParser::analyzeValue<unsigned int>(const std::string& str, bool /*space_delete*/)
{
return fromStringNumber<unsigned int>(str);
}

template<>
uint64 CommandLineParser::analyzeValue<uint64>(const std::string& str, bool /*space_delete*/)
{
return fromStringNumber<uint64>(str);
}

template<>
float CommandLineParser::analyzeValue<float>(const std::string& str, bool /*space_delete*/)
{
return fromStringNumber<float>(str);
}

template<>
double CommandLineParser::analyzeValue<double>(const std::string& str, bool /*space_delete*/)
{
return fromStringNumber<double>(str);
}


好多东西真的不用自己写.    联想很重要.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息